[OPENAM-15424] Setting auth_level on access token generation fails if the underlying SSO token is destroyed after the auth_code is generated Created: 11/Sep/19  Updated: 08/Jul/20  Resolved: 19/Dec/19

Status: Resolved
Project: OpenAM
Component/s: oauth2, session
Affects Version/s: 14.1.1, 5.5.1, 6.0.0, 6.5.1, 6.5.2, 6.5.2.1
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Darinder Shokar Assignee: Lawrence Yarham
Resolution: Won't Fix Votes: 0
Labels: EDISON
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Relates
relates to OPENAM-16474 id_token contains auth_time of 0 if s... Open
relates to OPENAM-15340 Ability to obtain original custom cla... Open
is related to OPENAM-11278 Add ability to associate AuthLevel wi... Resolved
Sprint: AM Sustaining Sprint 67, AM Sustaining Sprint 68, AM Sustaining Sprint 69, AM Sustaining Sprint 70
Story Points: 5
Support Ticket IDs:

 Description   

Background

To generate an authorization_code the user needs to be in an authenticated state - i.e. require an SSO token. However once the auth_code is generated, there should be no requirement for a valid SSO in order to generate the access/refresh/oidc_tokens.

In AM 5.1.1 there is a hard requirement for the above (i.e. calls to ../access_token fails is the parent SSO token is not valid and present). However from AM 5.5.x onward (looks to be as a result of https://bugster.forgerock.org/jira/browse/OPENAM-11797) there is no requirement for an SSO token once an auth_code has been created. Verified - deleted the parent SSO token post auth_code generation, hit ../access_token and access/refresh/oidc tokens generate successfully.

Issue

However, if the SSO token is deleted after the auth_code is generated the auth_level is omitted from the access token, which is causing downstream application failures which depend on auth_level being set.

Everything required to generate the access/refresh/oidc tokens should be baked in the auth_code - either the CoreTokenObject or as a separate attribute (latter probably more difficult as it would mean data model changes).

Example where SSO token is not deleted

Access token extract from CTS if SSO token is not deleted:

dn: coreTokenId=bkmk1kUDslQC7nSJKRzih0qYyvM,ou=famrecords,ou=openam-session,
ou=tokens,dc=openam,dc=forgerock,dc=org
objectClass: top
objectClass: frCoreToken
coreTokenId: bkmk1kUDslQC7nSJKRzih0qYyvM
....
coreTokenObject: {"clientID":["client"],"auth_level":10,"auditTrackingId":["
60a146bb-71bc-446a-8413-ca356c8d394f-415167"],"tokenName":["access_token"],
"userName":["demo"],"authGrantId":["QeUhTVcvfrXjB5OvKMg_3_9tfGg"],"nonce":[
],"expireTime":["1568210794652"],"grant_type":["authorization_code"],"scope
":["openid","profile"],"auth_time":["1568204791"],"realm":["/"],"id":["bkmk
1kUDslQC7nSJKRzih0qYyvM"],"tokenType":["Bearer"]}
.....

Call to ../tokeninfo for the above token:

{
  "token_type": "Bearer",
  "realm": "/",
  "client_id": "client",
  "expires_in": 5999,
  "access_token": "bkmk1kUDslQC7nSJKRzih0qYyvM",
  "grant_type": "authorization_code",
  "auth_level": 10,
  "openid": "",
  "scope": [
    "openid",
    "profile"
  ],
  "profile": ""
}

Call to ../introspect for the above token:

{
  "iss": "http://openam.test.com:9495/openam/oauth2",
  "auth_level": 10,
  "active": true,
  "scope": "openid profile",
  "client_id": "client",
  "user_id": "demo",
  "token_type": "Bearer",
  "exp": 1568210794,
  "sub": "demo"
}

Example where SSO token is deleted

Access token extract from CTS (auth_level is null and auth_time=0):

dn: coreTokenId=NbSoO1MQVqslESOibF8BYh0aw_4,ou=famrecords,ou=openam-session,
ou=tokens,dc=openam,dc=forgerock,dc=org
objectClass: top
objectClass: frCoreToken
....
coreTokenObject: {"clientID":["client"],"auth_level":null,"auditTrackingId":
["60a146bb-71bc-446a-8413-ca356c8d394f-416617"],"tokenName":["access_token"
],"userName":["demo"],"authGrantId":["ybGJtq83wQweQztMLVxnvFq9BUI"],"nonce"
:[],"expireTime":["1568211035653"],"grant_type":["authorization_code"],"sco
pe":["openid","profile"],"auth_time":["0"],"realm":["/"],"id":["NbSoO1MQVqs
lESOibF8BYh0aw_4"],"tokenType":["Bearer"]}
....

Call to ../tokeninfo for the above token:

{
  "expires_in": 5999,
  "client_id": "client",
  "access_token": "NbSoO1MQVqslESOibF8BYh0aw_4",
  "grant_type": "authorization_code",
  "openid": "",
  "scope": [
    "openid",
    "profile"
  ],
  "profile": "",
  "realm": "/",
  "token_type": "Bearer"
}

Call to ../introspect for the above token:

{
  "active": true,
  "scope": "openid profile",
  "client_id": "client",
  "user_id": "demo",
  "token_type": "Bearer",
  "exp": 1568211035,
  "sub": "demo",
  "iss": "http://openam.test.com:9495/openam/oauth2"
}



 Comments   
Comment by Lawrence Yarham [ 19/Dec/19 ]

The suggested solution here is to delay the point at which the user session is terminated until after the access_token is generated.

Generated at Wed Nov 25 08:44:07 UTC 2020 using Jira 7.13.12#713012-sha1:6e07c38070d5191bbf7353952ed38f111754533a.