Skip to content

Commit

Permalink
update for onboarding tech checklist
Browse files Browse the repository at this point in the history
  • Loading branch information
jack-coggin committed Nov 20, 2023
1 parent 703d642 commit 2d46c4f
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 10 deletions.
11 changes: 6 additions & 5 deletions app/controllers/users/omniauth_callbacks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,19 @@ def openid_connect

auth_service = GovOneAuthService.new(code: params['code'])
tokens_response = auth_service.tokens

return error_redirect unless valid_tokens?(tokens_response)

id_token = tokens_response['id_token']
session[:id_token] = id_token
gov_one_id = auth_service.decode_id_token(id_token)[0]['sub']
id_token = auth_service.decode_id_token(tokens_response['id_token'])[0]
session[:id_token] = tokens_response['id_token']
gov_one_id = id_token['sub']
return error_redirect unless auth_service.valid_id_token?(id_token, session[:gov_one_auth_nonce])

user_info_response = auth_service.user_info(tokens_response['access_token'])
email = user_info_response['email']
return error_redirect unless valid_user_info?(user_info_response)

gov_user = User.find_or_create_from_gov_one(email: email, gov_one_id: gov_one_id)
session.delete(:nonce)
sign_in_and_redirect gov_user if gov_user
end

Expand All @@ -40,7 +41,7 @@ def valid_tokens?(tokens_response)
# @param user_info_response [Hash]
# @return [Boolean]
def valid_user_info?(user_info_response)
user_info_response.present? && user_info_response['email'].present?
user_info_response.present? && user_info_response['email'].present? && user_info_response['sub'] == session[:id_token]['sub']
end

# @return [nil]
Expand Down
3 changes: 2 additions & 1 deletion app/helpers/gov_one_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ def login_uri
client_id: Rails.application.config.gov_one_client_id,
response_type: 'code',
scope: 'email openid',
nonce: SecureRandom.uuid,
nonce: SecureRandom.alphanumeric(25),
state: SecureRandom.uuid,
}

session[:gov_one_auth_state] = params[:state]
session[:gov_one_auth_nonce] = params[:nonce]

gov_one_uri(:login, params)
end
Expand Down
24 changes: 20 additions & 4 deletions app/services/gov_one_auth_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ def tokens
{}
end

# @param token [String]
# @param nonce [String]
# @return [Boolean]
def valid_id_token?(token, nonce)
token['iss'] == "#{Rails.application.config.gov_one_base_uri}/" &&
token['aud'] == Rails.application.config.gov_one_client_id &&
token['nonce'] == nonce
end

# GET /userinfo
# @param access_token [String]
# @return [Hash]
Expand Down Expand Up @@ -66,7 +75,7 @@ def decode_id_token(token)
key_params = jwks['keys'].find { |key| key['kid'] == kid }
jwk = JWT::JWK.new(key_params)

JWT.decode(token, jwk.public_key, true, algorithm: 'ES256')
JWT.decode(token, jwk.public_key, true, { verify_iat: true, algorithm: 'ES256' })
end

# @param address [String]
Expand All @@ -80,11 +89,18 @@ def build_http(address)

private

# @return [Hash]
def fetch_and_cache_jwks
Rails.cache.fetch('jwks', expires_in: 24.hours) do
uri, http = build_http(ENDPOINTS[:jwks])
response = http.request(Net::HTTP::Get.new(uri.path))
JSON.parse(response.body)
end
end

# @return [Hash]
def jwks
uri, http = build_http(ENDPOINTS[:jwks])
response = http.request(Net::HTTP::Get.new(uri.path))
JSON.parse(response.body)
@jwks ||= fetch_and_cache_jwks
end

# @return [String]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
allow(auth_service).to receive(:user_info).and_return({ 'email' => email })
allow(auth_service).to receive(:jwt_assertion).and_return('mock_jwt_assertion')
allow(auth_service).to receive(:decode_id_token).and_return([{ 'sub' => 'mock_sub' }])
allow(auth_service).to receive(:valid_id_token?).and_return(true)
end

context 'with a new user' do
Expand Down

0 comments on commit 2d46c4f

Please sign in to comment.