lib/rodauth/features/oidc.rb in rodauth-oauth-1.0.0.pre.beta2 vs lib/rodauth/features/oidc.rb in rodauth-oauth-1.0.0
- old
+ new
@@ -290,10 +290,15 @@
request.params["scope"] = sc.join(" ")
end
super
+
+ return unless (response_type = param_or_nil("response_type"))
+ return unless response_type.include?("id_token")
+
+ redirect_response_error("invalid_request") unless param_or_nil("nonce")
end
def require_authorizable_account
try_prompt
super
@@ -438,14 +443,11 @@
else
oauth_grant = valid_oauth_grant_ds.where(oauth_grants_code_column => authorization_code).first
_generate_access_token(oauth_grant)
end
- {
- "code" => authorization_code,
- **json_access_token_payload(oauth_grants_token_column => access_token)
- }
+ json_access_token_payload(oauth_grants_token_column => access_token).merge("code" => authorization_code)
end
def create_token(*)
oauth_grant = super
generate_id_token(oauth_grant)
@@ -455,19 +457,32 @@
def generate_id_token(oauth_grant, include_claims = false)
oauth_scopes = oauth_grant[oauth_grants_scopes_column].split(oauth_scope_separator)
return unless oauth_scopes.include?("openid")
+ signing_algorithm = oauth_application[oauth_applications_id_token_signed_response_alg_column] ||
+ oauth_jwt_keys.keys.first
+
id_token_claims = jwt_claims(oauth_grant)
id_token_claims[:nonce] = oauth_grant[oauth_grants_nonce_column] if oauth_grant[oauth_grants_nonce_column]
id_token_claims[:acr] = oauth_grant[oauth_grants_acr_column] if oauth_grant[oauth_grants_acr_column]
# Time when the End-User authentication occurred.
id_token_claims[:auth_time] = get_oidc_account_last_login_at(oauth_grant[oauth_grants_account_id_column]).to_i
+ # Access Token hash value.
+ if (access_token = oauth_grant[oauth_grants_token_column])
+ id_token_claims[:at_hash] = id_token_hash(access_token, signing_algorithm)
+ end
+
+ # code hash value.
+ if (code = oauth_grant[oauth_grants_code_column])
+ id_token_claims[:c_hash] = id_token_hash(code, signing_algorithm)
+ end
+
account = db[accounts_table].where(account_id_column => oauth_grant[oauth_grants_account_id_column]).first
# this should never happen!
# a newly minted oauth token from a grant should have been assigned to an account
# who just authorized its generation.
@@ -486,14 +501,11 @@
# the resulting Claims are returned in the ID Token.
fill_with_account_claims(id_token_claims, account, oauth_scopes, param_or_nil("claims_locales")) if include_claims
params = {
jwks: oauth_application_jwks(oauth_application),
- signing_algorithm: (
- oauth_application[oauth_applications_id_token_signed_response_alg_column] ||
- oauth_jwt_keys.keys.first
- ),
+ signing_algorithm: signing_algorithm,
encryption_algorithm: oauth_application[oauth_applications_id_token_encrypted_response_alg_column],
encryption_method: oauth_application[oauth_applications_id_token_encrypted_response_enc_column]
}.compact
oauth_grant[:id_token] = jwt_encode(id_token_claims, **params)
@@ -653,19 +665,21 @@
"code" => params["code"]
)
when "id_token token"
redirect_response_error("invalid_request") unless supports_token_response_type?
- oauth_grant = _do_authorize_token(oauth_grants_type_column => "hybrid")
+ grant_params = oidc_grant_params.merge(oauth_grants_type_column => "hybrid")
+ oauth_grant = _do_authorize_token(grant_params)
generate_id_token(oauth_grant)
response_params.replace(json_access_token_payload(oauth_grant))
when "code id_token token"
redirect_response_error("invalid_request") unless supports_token_response_type?
params = create_oauth_grant_with_token
oauth_grant = valid_oauth_grant_ds.where(oauth_grants_code_column => params["code"]).first
+ oauth_grant[oauth_grants_token_column] = params["access_token"]
generate_id_token(oauth_grant)
response_params.replace(params.merge("id_token" => oauth_grant[:id_token]))
when "none"
response_mode ||= "none"
@@ -782,8 +796,22 @@
else
response["Cache-Control"] = "no-store"
response["Pragma"] = "no-cache"
end
return_response(jwt)
+ end
+
+ def id_token_hash(hash, algo)
+ digest = case algo
+ when /256/ then Digest::SHA256
+ when /384/ then Digest::SHA384
+ when /512/ then Digest::SHA512
+ end
+
+ return unless digest
+
+ hash = digest.digest(hash)
+ hash = hash[0...hash.size / 2]
+ Base64.urlsafe_encode64(hash).tr("=", "")
end
end
end