How to get new access token in OpenID Connect/OAuth2 Implicit Flow
Asked Answered
M

2

6

I am currently using OpenID Connect/Oauth2 Implicit Flow in a mobile app. I am bringing up a Web View for the user to login and obtaining the access token and expiry. However, when the access token expires, do I need to ask the user to log in again? Or is there a way to get a new access token silently using the current one, without bugging the user. I guess another option is to set the token expiry to be a really long time, but I have read that this is a bad idea.

Am I missing something here?

Mulciber answered 29/6, 2017 at 1:30 Comment(3)
Do you have to use the webview and the Implicit flow or is it your choice?Stonefly
I am trying to access Couchbase Sync Gateway, and based on this discussion I had on their forums forums.couchbase.com/t/cbl-database-name/13233/18, it seems I need to use Implicit flow. My identity provider (keycloak) recommends using their web login/registration pages - therefore web view.Mulciber
Please provide a stackoverflow.com/help/mcve(Minimal, Complete, and Verifiable example)Nebraska
N
6

Since Implicit flow does not send a refresh token (as explained in section 9 of RFC6746), usage of refresh tokens is not possible. But as a workaround, one can use client credential grant to obtain an access token.

A viable solution is to first follow the implicit flow and authenticate the client. Then client authentication grant can be used to do the required API calls.

Sample request (from RFC6749)

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

 grant_type=client_credentials

Sample resposne (from RFC6749)

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
   "access_token":"2YotnFZFEjr1zCsicMWpAA",
   "token_type":"example",
   "expires_in":3600,
   "example_parameter":"example_value"
}

P.S - If you are using authorization code flow, you can use refresh_token to get a new access token. How the request should be formed can be obtained from OAuth2 documentation. Note that to do so, your authorization response should contain a `refresh_token.

A refresh token should be protected as valuable as a credential for a user. More can be read from keycloak documentation from here

Sample request and a response (from RFC6749)

Request

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA

Response

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
  "access_token": "TlBN45jURg",
  "token_type": "Bearer",
  "refresh_token": "9yNOxJtZa5",
  "expires_in": 3600
}
Newsmonger answered 3/7, 2017 at 4:17 Comment(7)
With "Implicit flow" there is no such thing as refresh tokens.Mulciber
Okay I missed this in the specification " When using the implicit grant type flow, a refresh token is not returned, which requires repeating the authorization process once the access token expires." Is there any reason why you cannot use Authorisation code flow ?Newsmonger
Because I'm using it in conjunction with Couchbase Sync Gateway - they have essentially recommended to use it. See forums convo I had with them - forums.couchbase.com/t/cbl-database-name/13233/18Mulciber
Interesting case. Now here is a place where client credential grant can be used [tools.ietf.org/html/rfc6749#section-4.4]. How it can be used will depend on what Keycloak provides. Initially you need to authenticate end user. And once that done you can use client credential grant. But you need to have proper authorisation grants in place. This way you can improve user experience. (A tricky solution IMO)Newsmonger
Thanks for the research. I'll look into it and let you know how I go.Mulciber
Ok. I've got client credentials working. Specifically grant_type=password. This gives me a new token when I find that the old one expires. Thanks. Put this as the answer and I'll accept it.Mulciber
@tura08 Glad it helped you. Answer is changed to reflect the changeNewsmonger
P
0

The recommended way is to use an external browser and the Authorization Code Flow. Check the OAuth 2.0 for Native Apps RFC. For Android, there is also a supporting library AppAuth. With this flow, you can use a refresh token to get a new access token, but there is an issue with a client secret (usually needed for accessing /token endpoint), because you cannot keep it safe in a mobile app (it's described in the RFC).

If you decide to stick with the WebView and the Implicit Flow, which is not safe (your app can see the password) you could use the same technique as in JavaScript applications - request a new token with /auth?...&prompt=none URL which will return a new token without asking the user for credentials if he still has an open session there.

Pew answered 29/6, 2017 at 7:23 Comment(2)
I've looking into using chrome custom tabs. unfortunately, I don't think Keycloak allows prompt=none.Mulciber
prompt=none can be only used if you have a valid user logged in status in identity provider. Once the tokens expires, there won't be a valid session (That's how most identity providers handle it). So the prompt=none can be used before token expires. Anyway, refresh_tokens are the right wayNewsmonger

© 2022 - 2024 — McMap. All rights reserved.