Need help interpreting cascade on InvalidateToken

Not applicable

I'm looking at http://apigee.com/docs/api-services/content/validating-and-invalidating-access-tokens and am hoping someone can help clarify the cascade option. I have bolded two statements that appear to be conflicting. The top section seems to indicate that you cannot use a refresh token once the access token has been revoked. The bottom section says that the cascade parameter controls that. So it seems that cascade=false will not revoke the refresh token but it can't be used. What am I missing? Thanks.

Doc text:

Token expiration is independent of the state of the token (approved or revoked). If you revoke an access token, its associated refresh token cannot be used to refresh the revoked access token.

...

  • cascade (optional, boolean): By default, this option is set to true, and causes the revocation to propagate to associated tokens. So, if applied to a refresh token, its associated access token is also revoked. If applied to an access token, its associated refresh token is also revoked. If you set this tofalse, then only the specified access or refresh token is revoked.
Solved Solved
1 16 2,128
1 ACCEPTED SOLUTION

@Jeff Nadeau After a little checking, I confirmed that the first note you refer to above was worded incorrectly. The correct wording is below. The doc has been updated. Otherwise, the description of "cascade" is correct. That was a good catch -- thanks for raising the question.

"Token expiration is independent of the state of the token (approved or revoked). If a refresh token has expired, you cannot use it to refresh an access token."

View solution in original post

16 REPLIES 16

Hi Jeff,

UPDATE:

This statement seems confusing but It reflects how it works. If an access token is revoked, the refresh token associated with that becomes useless - cannot be used to get new access tokens, irrespective of cascade parameter.

--------

"If you revoke an access token, its associated refresh token cannot be used to refresh the revoked access token."

So, the expectations are,

If you revoke a access token, its revoked and you can't use it again

If you have refresh token, you can use it to get a new access token

If you revoke a refresh token, its revoked and you can't use it to request a access token.

--

We have filed a JIRA to track this

Thanks,

Thanks for the quick response! My expectation is that if you revoke an access token with cascade=false then another access token can be obtained using the refresh token (that was returned when the access token was issued). This is to implement session logout without requiring another three-legged Oauth session.

Our experience with access token invalidation with cascase=false is that the refresh token is still valid when queried but it does not allow a new access token to be issued. So it does seem to technically follow the documentation but a valid refresh token that cannot be used to issue another access token seems useless. I can submit a support ticket--I just wanted to make sure I wasn't missing something. Thanks.

Thanks @Jeff Nadeau for reporting this issue. I was able to replicate it on a free org. Refresh tokens cannot be used to generate new access tokens, even when cascade is set to false.

This has been reported on APIRT-1390. Please submit a support ticket providing a reference to this JIRA ticket.

@Srini Chebrolu, @mukundha@apigee.com. Any suggestions on this?

Thanks @dzuluaga. I added the JIRA ticket number to the support ticket I had created. Also, is there a work-around for this? In other words, is there a way for me to make an access token invalid without affecting the refresh token?

@Jeff Nadeau

i have confirmed with our poduct engineering this is how the current implementation works.. sorry for the confusion earlier, So we have created this issue.

Unfortunately, for now, I don think you can invalidate only the access token.

But to implement the logout usecase - i think we would need to model the user's consent [maybe in Baas], that way applications need not go thro the whole end user consent process everytime.

So, First time an app requests a token, we get consent from user and store it in baas.

1) App gets the token, uses it - user click on logout -> token is invalidated, else token is refreshed using the refresh token

2) New login from the user, app requests token, we check for existing user's consent - if it exists provide a new token, else similar to step 1

3) User decides to revoke consent for an app, that time we remove the consent from the Baas

So basically the idea is model user's consent separately - it would also provide flexibility in how your users can manage their consents

Thanks,

@mukundha@apigee.com Thanks for the suggestion. We don't have BaaS, but I suppose we could store in a KVM. However, I really do not want to model consent--I want the existence of the refresh token to be consent. That way I don't need to worry about them being in sync and extending my APIs. Plus I have to keep track of what scopes the consent was for. This is all what the refresh token has. However, I may need to do something like that because of this issue if there is no other work-around.

@Mukundha Madhavan so do we have a workaround to resolve the issue in this case?

@Jeff Nadeau - that seems like a reasonable expectation. eg, after revoking an access token with cascade=false then another access token can be obtained using the refresh token.

@Jeff Nadeau After a little checking, I confirmed that the first note you refer to above was worded incorrectly. The correct wording is below. The doc has been updated. Otherwise, the description of "cascade" is correct. That was a good catch -- thanks for raising the question.

"Token expiration is independent of the state of the token (approved or revoked). If a refresh token has expired, you cannot use it to refresh an access token."

@wwitman If you are going to address the documentation issues then this will also need to be either changed or the product defect will need to be addressed. Setting it to false does not work that way.

  • cascade (optional, boolean): By default, this option is set to true, and causes the revocation to propagate to associated tokens. So, if applied to a refresh token, its associated access token is also revoked. If applied to an access token, its associated refresh token is also revoked. If you set this tofalse, then only the specified access or refresh token is revoked.

@Jeff Nadeau I updated the doc with a note explaining the current behavior. Thanks for the reminder. We're tracking this and will update the doc if this is addressed in the product.

adas
Participant V

Let me explain the use of the cascade flag.

Below are the 4 cases:

case 1: cascade=true and type=access_token: This would revoke the access_token and the associated refresh_token too.

case 2: cascade=false and type=access_token: This would revoke the access_token but not the refresh_token associated with it.

case 3: cascade=true and type=refresh_token: This would revoke the refresh_token and the associated access_token(s)

case 4: cascade=false and type=refresh_token: This would revoke the refresh_token but not the associated access_token(s)

NOTE: When the refresh_token is used to generate a new access_token, we check the status of the original access_token and throw an error if the access token is revoked: com.apigee.oauth.v2.TokenGenerationException: Access Token not approved. 

To understand why it is implemented this way, let's take a few use-cases:

Say your access_token is compromised, so you would want to revoke the access_token. You can choose to revoke both the access_token and the refresh_token(case 1) or just the access token (case 2). In both cases, we cannot use the refresh_token to generate new tokens.

The reason for this is: if someone has got hold of your access_token, they can make the access_token details call and also get hold of your refresh_token, which means both are compromised, and hence the feature is implemented this way. 

So the question now is, "what's the use of the cascade query param?".

The real use of the cascade flag is when you revoke a refresh token. Say you decide that you want to prevent any further generation of access tokens for a refresh_token but you want to keep the existing tokens and let them continue to work. So you would use case 4 by setting cascade=false for revoking the refresh_token. The other usecase, where you would want to revoke both the refresh_token and the access_token, that's where case 3 comes in.

I think this is working the way its designed and doesn't require any changes. For case 1 and case 2, generating new access tokens is the way to go instead of trying to use refresh token to generate new access tokens.

If the use-case is around session management then you should set the access token expiry to be close to the session timeout value instead of trying call the revoke token api when session expires. That way the access_token expires, but you can still work with the refresh_token to generate new tokens without asking for the user consent. Hope this explains.

Thanks for the explanation @arghya das. The explanation on the "real" use of the cascade flag makes perfect sense and was never in doubt. Completely understand the use on a refresh token.

We will agree to disagree on the need for cascade=false for revoking an access token. I will implement the behavior outside of the invalidate policy. My major issues with your explanation are:

  1. What good is a refresh token that cannot be used to generate an access token? Saying that you are not revoking the refresh token but not allowing it to generate access tokens appears to be a contortion that is just plain confusing.
  2. In the case of a compromised access token I would have the option of setting cascade=true. So your argument becomes that the only reasonable case of needing to revoke an access token is because it is compromised. My customer and I disagree.
  3. I would not consider setting access token expiry being close to session timeout to be session management. I need to really manage the session when someone hits the logout button. Granted there are other ways, but what you describe is not "close enough".

I do appreciate your time. I will implement this by a custom attribute called "active" on the access token and check it every time I need to. I will then set it to false if someone revokes it. I will allow them to send a cascade flag to cause the cascade effect if they choose.

adas
Participant V

@Jeff Nadeau I see your point, but I have one question on the use case and how its being handled. If the user hits the logout button (which is different from a session expiry scenario), should the user be shown the consent page again when he tries to log back in. Which means you go through the generate access token flow, rather than trying to exchange the refresh token for a new access token.

The purpose of the revoke action is primarily around security aspects and should address cases like compromised tokens, rogue apps etc. You may choose to disagree and implement a different use case which uses the same policy flow, that's entirely upto the use case you are trying to implement. I was explaining the out of the box behaviour of the policies.

@arghya das The way it was described to me (through a solution architect) is that the application obtains an access token and uses it during a session. Those sessions must be able to be terminated on demand. Then the user should not have to provide consent again after terminating a session. We have chosen to associate consent with the existence of a valid refresh token, hence the need for this feature.

I do understand your point about the intent and I also understand that we may be going off the beaten path here. When all is said and done this really was a simple issue of the documentation of the cascade flag instead of an absolute expectation that Apigee must have this functionality. However, I still feel pretty strongly about my point #1 above, so I think that the doc should be updated so someone doesn't run into the same thing.

We will proceed with our alternate implementation for our upcoming release. Thanks.

adas
Participant V
@wwitman

Can you do the needful. Also refer to the internal JIRA ticket which tracks this for further updates.