Add fbos_version as a param to token creation
parent
694bcddce3
commit
1bc9cf98e5
|
@ -166,11 +166,20 @@ private
|
|||
end
|
||||
|
||||
EXPECTED_VER = Gem::Version::new('5.0.0')
|
||||
|
||||
# Try to extract FarmBot OS version from user agent.
|
||||
# If none found, return lowest allowable version + 1 "tiny" bump to prevent
|
||||
# lockouts.
|
||||
def fbos_version
|
||||
when_farmbot_os do
|
||||
Gem::Version::new(pretty_ua.upcase.split("/").last.split(" ").first)
|
||||
end || EXPECTED_VER.bump
|
||||
end
|
||||
|
||||
# This is how we lock old versions of FBOS out of the API:
|
||||
def check_fbos_version
|
||||
when_farmbot_os do
|
||||
semver = pretty_ua.upcase.split("/").last.split(" ").first
|
||||
bad_version unless Gem::Version::new(semver) >= EXPECTED_VER
|
||||
bad_version unless fbos_version >= EXPECTED_VER
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -8,7 +8,8 @@ module Api
|
|||
|
||||
# Give you the same token, but reloads all claims except `exp`
|
||||
def show
|
||||
mutate Auth::ReloadToken.run(jwt: request.headers["Authorization"])
|
||||
mutate Auth::ReloadToken.run(jwt: request.headers["Authorization"],
|
||||
fbos_version: fbos_version)
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -48,7 +49,9 @@ module Api
|
|||
credentials: user[:credentials],
|
||||
agree_to_terms: !!user[:agree_to_terms],
|
||||
host: $API_URL,
|
||||
aud: guess_aud_claim })
|
||||
aud: guess_aud_claim,
|
||||
fbos_version: fbos_version
|
||||
})
|
||||
else
|
||||
render json: {error: NO_USER_ATTR}, status: 422
|
||||
end
|
||||
|
|
|
@ -20,7 +20,8 @@ class SessionToken < AbstractJwtToken
|
|||
iat: Time.now.to_i,
|
||||
exp: EXPIRY.from_now.to_i,
|
||||
iss: $API_URL,
|
||||
aud: AbstractJwtToken::UNKNOWN_AUD)
|
||||
aud: AbstractJwtToken::UNKNOWN_AUD,
|
||||
fbos_version:) # Gem::Version
|
||||
|
||||
unless user.verified?
|
||||
Rollbar.info("Verification Error", email: user.email)
|
||||
|
@ -42,9 +43,10 @@ class SessionToken < AbstractJwtToken
|
|||
vhost: VHOST }])
|
||||
end
|
||||
|
||||
def self.as_json(user, aud)
|
||||
{ token: SessionToken.issue_to(user,
|
||||
iss: $API_URL, aud: aud),
|
||||
def self.as_json(user, aud, fbos_version)
|
||||
{ token: SessionToken.issue_to(user, iss: $API_URL,
|
||||
aud: aud,
|
||||
fbos_version: fbos_version),
|
||||
user: user }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,6 +5,7 @@ module Auth
|
|||
required do
|
||||
string :email
|
||||
string :password
|
||||
model :fbos_version, class: Gem::Version
|
||||
end
|
||||
|
||||
optional do
|
||||
|
@ -24,7 +25,7 @@ module Auth
|
|||
|
||||
def execute
|
||||
@user.update_attributes(agreed_to_terms_at: Time.now) if agree_to_terms
|
||||
SessionToken.as_json(@user, aud)
|
||||
SessionToken.as_json(@user, aud, fbos_version)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -9,6 +9,7 @@ module Auth
|
|||
|
||||
required do
|
||||
string :credentials
|
||||
model :fbos_version, class: Gem::Version
|
||||
end
|
||||
|
||||
def validate
|
||||
|
@ -22,7 +23,7 @@ module Auth
|
|||
end
|
||||
|
||||
def execute
|
||||
SessionToken.as_json(user, AbstractJwtToken::BOT_AUD)
|
||||
SessionToken.as_json(user, AbstractJwtToken::BOT_AUD, fbos_version)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -5,7 +5,10 @@ module Auth
|
|||
attr_reader :user
|
||||
BAD_SUB = "Please log out and try again."
|
||||
|
||||
required { string :jwt }
|
||||
required do
|
||||
string :jwt
|
||||
model :fbos_version, class: Gem::Version
|
||||
end
|
||||
|
||||
def validate
|
||||
@user = User.find_by_email_or_id(claims["sub"])
|
||||
|
@ -14,8 +17,9 @@ module Auth
|
|||
def execute
|
||||
security_criticial_danger = claims["exp"] # Stop infinite sessions
|
||||
token = SessionToken.issue_to(user,
|
||||
aud: claims["aud"],
|
||||
exp: security_criticial_danger)
|
||||
aud: claims["aud"],
|
||||
exp: security_criticial_danger,
|
||||
fbos_version: fbos_version)
|
||||
return { token: token }
|
||||
end
|
||||
|
||||
|
|
|
@ -16,8 +16,9 @@ module PasswordResets
|
|||
def execute
|
||||
user.update_attributes!(password: password,
|
||||
password_confirmation: password_confirmation)
|
||||
Auth::CreateToken.run!(email: user.email,
|
||||
password: password)
|
||||
Auth::CreateToken.run!(email: user.email,
|
||||
password: password,
|
||||
fbos_version: Gem::Version.new("999.9.9"),)
|
||||
rescue JWT::ExpiredSignature
|
||||
add_error :reset, :too_old, OLD_TOKEN
|
||||
end
|
||||
|
|
|
@ -6,7 +6,8 @@ module Users
|
|||
user.update_attributes!(confirmed_at: Time.now,
|
||||
email: user.unconfirmed_email,
|
||||
unconfirmed_email: nil)
|
||||
SessionToken.as_json(user, AbstractJwtToken::HUMAN_AUD)
|
||||
fbos_vers = Gem::Version.new("99.9.9") # Not relevant here, stubbing out.
|
||||
SessionToken.as_json(user, AbstractJwtToken::HUMAN_AUD, fbos_vers)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,7 +9,9 @@ module Users
|
|||
def execute
|
||||
user.confirmed_at = Time.now
|
||||
user.save!
|
||||
SessionToken.as_json(user.reload, AbstractJwtToken::HUMAN_AUD)
|
||||
SessionToken.as_json(user.reload,
|
||||
AbstractJwtToken::HUMAN_AUD,
|
||||
Gem::Version.new("99.9.9"))
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -19,15 +19,16 @@ describe Api::PasswordResetsController do
|
|||
end
|
||||
|
||||
it 'resets password using a reset token' do
|
||||
params = { password: "xpassword123",
|
||||
password_confirmation: "xpassword123",
|
||||
id: PasswordResetToken
|
||||
params = {password: "xpassword123",
|
||||
password_confirmation: "xpassword123",
|
||||
fbos_version: Gem::Version.new("999.9.9"),
|
||||
id: PasswordResetToken
|
||||
.issue_to(user)
|
||||
.encoded }
|
||||
put :update, params: params
|
||||
expect(user
|
||||
.reload
|
||||
.valid_password?(params[:password])).to eq(true)
|
||||
.reload
|
||||
.valid_password?(params[:password])).to eq(true)
|
||||
expect(response.status).to eq(200)
|
||||
expect(json.keys).to include(:token)
|
||||
expect(json.keys).to include(:user)
|
||||
|
|
|
@ -8,8 +8,10 @@ describe Api::PointsController do
|
|||
FactoryBot.create(:user, device: device, password: "password123")
|
||||
end
|
||||
let(:auth_token) do
|
||||
Auth::CreateToken
|
||||
.run!(email: user.email, password: "password123")[:token].encoded
|
||||
params = {email: user.email,
|
||||
password: "password123",
|
||||
fbos_version: Gem::Version.new("999.9.9")}
|
||||
Auth::CreateToken.run!(params)[:token].encoded
|
||||
end
|
||||
|
||||
it 'lists points' do
|
||||
|
|
|
@ -6,7 +6,9 @@ describe Api::TokensController do
|
|||
|
||||
describe '#show' do
|
||||
let(:user) { FactoryBot.create(:user, password: "password") }
|
||||
let(:auth_token) { SessionToken.issue_to(user) }
|
||||
let(:auth_token) do
|
||||
SessionToken.issue_to(user, fbos_version: Gem::Version.new("9.9.9"))
|
||||
end
|
||||
|
||||
it 'creates a new token' do
|
||||
request.headers["Authorization"] = "bearer #{auth_token.encoded}"
|
||||
|
|
|
@ -30,12 +30,18 @@ describe SessionToken do
|
|||
end
|
||||
|
||||
it 'issues a token to a user' do
|
||||
SessionToken.issue_to(user, iat: 000, exp: 456, iss: "//lycos.com:9867")
|
||||
SessionToken.issue_to(user, iat: 000,
|
||||
exp: 456,
|
||||
iss: "//lycos.com:9867",
|
||||
fbos_version: Gem::Version.new("9.9.9"))
|
||||
end
|
||||
|
||||
it "doesn't honor expired tokens" do
|
||||
user.update_attributes!(confirmed_at: Time.now)
|
||||
token = SessionToken.issue_to(user, iat: 000, exp: 1, iss: "//lycos.com:9867")
|
||||
token = SessionToken.issue_to(user, iat: 000,
|
||||
exp: 1,
|
||||
iss: "//lycos.com:9867",
|
||||
fbos_version: Gem::Version.new("9.9.9"))
|
||||
result = Auth::FromJWT.run(jwt: token.encoded)
|
||||
expect(result.success?).to be(false)
|
||||
expect(result.errors.values.first.message)
|
||||
|
@ -46,7 +52,10 @@ describe SessionToken do
|
|||
it "doesn't mint tokens for unverified users" do
|
||||
user.update_attributes!(confirmed_at: nil)
|
||||
expect {
|
||||
SessionToken.issue_to(user, iat: 000, exp: 1, iss: "//lycos.com:9867")
|
||||
SessionToken.issue_to(user, iat: 000,
|
||||
exp: 1,
|
||||
iss: "//lycos.com:9867",
|
||||
fbos_version: Gem::Version.new("9.9.9"))
|
||||
}.to raise_error(Errors::Forbidden)
|
||||
end
|
||||
else
|
||||
|
|
|
@ -12,7 +12,8 @@ describe Auth::FromJWT do
|
|||
end
|
||||
|
||||
it 'rejects bad credentials' do
|
||||
results = Auth::CreateTokenFromCredentials.run(credentials: "FOO" )
|
||||
results = Auth::CreateTokenFromCredentials
|
||||
.run(credentials: "FOO", fbos_version: Gem::Version.new("999.9.9"))
|
||||
expect(results.success?).to eq(false)
|
||||
expect(results.errors.message_list)
|
||||
.to include(Auth::CreateTokenFromCredentials::BAD_KEY)
|
||||
|
@ -23,7 +24,8 @@ describe Auth::FromJWT do
|
|||
user = FactoryBot.create(:user, password: pw)
|
||||
email = user.email
|
||||
creds = fake_credentials(email, pw)
|
||||
results = Auth::CreateTokenFromCredentials.run!(credentials: creds)
|
||||
results = Auth::CreateTokenFromCredentials
|
||||
.run!(credentials: creds, fbos_version: Gem::Version.new("999.9.9"))
|
||||
expect(results[:token]).to be_kind_of(SessionToken)
|
||||
expect(results[:user]).to eq(user)
|
||||
end
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
require "spec_helper"
|
||||
|
||||
describe Auth::FromJWT do
|
||||
FAKE_VERS = Gem::Version.new("99.9.9")
|
||||
let(:user) { FactoryBot.create(:user) }
|
||||
let(:token) { SessionToken.issue_to(user).encoded }
|
||||
let(:token) do
|
||||
SessionToken.issue_to(user, fbos_version: FAKE_VERS).encoded
|
||||
end
|
||||
|
||||
fake = -> (sub) {
|
||||
AbstractJwtToken.new([{ sub: sub,
|
||||
iat: Time.now.to_i,
|
||||
|
|
Loading…
Reference in New Issue