Keycloak - Implicit Flow Support

Authorization Code flow

  • Basic flow described in OAuth2 and OpenID Connect 1 specifications
  • Supported in Keycloak from it's early days

Step A

  • User accesses secured URL on application side (or click login)
  • Application redirects browser to Keycloak with Authorization Request

Authorization request example

http://localhost:8080/auth/realms/example/protocol/openid-connect/auth
  ?client_id=js-console
  &redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fjs-console%2F
  &state=aea3526d-ee91-4f17-b262-d794e49e16d0
  &response_type=code

Step B

Keycloak authenticates user (doesn't matter how) and optionally show grant screen

Step C

  • Authorization Response - Keycloak redirects through user's browser to the application with code and state parameters
  • URL of redirection was specified by redirect_uri parameter sent earlier in Authorization Request
  • Must be allowed in client configuration in Keycloak admin console (Valid Redirect URIs)

Authorization response example

http://localhost:8080/js-console/
  ?state=aea3526d-ee91-4f17-b262-d794e49e16d0   &code=TNe8_fSjxFRQhaI78SjxbScncZ3Roy5lJQIEiLCiXBE.0a55d203-9f7f-4b52-b496-e23b1477fd0b

Step D and E

  • Client application sends out-of-bound request to exchange code for token
  • Browser is not involved in typical server-side applications
  • Token request is POST request. It contains code and is authenticated with client credentials
  • Token response contains:
    • access_token
    • id_token
    • refresh_token
  • Both client credentials and tokens are hidden from browser (and user) in server-side applications

Token request example

POST: http://localhost:8080/auth/realms/example/protocol/openid-connect/token

  code=TNe8_fSjxFRQhaI78SjxbScncZ3Roy5lJQIEiLCiXBE.0a55d203-9f7f-4b52-b496-e23b1477fd0b
  &grant_type=authorization_code
  &client_id=js-console
  &redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fjs-console%2F

Response from token request

{
  "access_token":"eyJhbGciOiJSUzI1...",
  "expires_in":300,
  "refresh_token":"eyJhbGciOiJSU...",
  "refresh_expires_in":1800,
  "token_type":"bearer",
  "id_token":"eyJhbGc...",
  "not-before-policy":0,
  "session-state":"f58c76c1-85b9-4bbb-a26d-ebf56ec47334"
}

Implicit flow

  • Described in OAuth2 and OpenID Connect 1 specifications
  • Supported in Keycloak from 1.7

Step A

  • Authorization Request quite similar like in Authorization Code flow. But:
  • response_type=id_token token

Step C - Authorization Response

  • Parameters sent in URL fragment (not in query like Authorization Code Flow)
  • contains access_token and id_token. Doesn't contain code or refresh_token

Authorization response example

http://localhost:8080/js-console/
  #access_token=eyJhbGciOiJSUzI1...
  &expires_in=300
  &token_type=bearer
  &id_token=eyJhbGc...
  & not-before-policy=0
  &session-state=f58c...

Step D and E

  • Browser redirects the Authorization response to the application, but without fragment parameters
  • Access token and ID token not sent to the server-side of client application
  • Application returns the HTML page with keycloak.js adapter
  • keycloak.js adapter parses tokens from fragment and save them locally.
  • Fragment part is removed from browser history

Implicit flow details

  • There is no separate Token request ( code-to-token ) request needed
  • There are no client credentials
  • There is no refresh token
  • Typical usage in javascript applications

Keycloak and implicit flow

  • Flag on client details in admin console, whether implicit flow is enabled or not
  • Flag disabled by default
  • Separate timeout for Access tokens issued during implicit flow (15 minutes by default)
  • keycloak.js provides callback function onTokenExpired , which allows application to handle token expiration

Keycloak and implicit flow

  • keycloak.js still uses standard (Authorization Code) flow by default because:
  • There is no refresh token in implicit flow
  • Tokens sent in URL fragment. Security implications

Use implicit flow in keycloak.js

  • Use parameter to keycloak.init like:
  • keycloak.init({ flow: 'implicit' })

Hybrid flow

  • Described in OpenID Connect 1 specification

Step A

  • Authorization Request has response_type with both code and tokens.
  • response_type=code id_token token

Authorization Response

  • Parameters sent in URL fragment (like for implicit flow)
  • contains code and access_token and id_token
  • Application can immediately use accessToken and IDToken from URL fragment
  • In addition, it can use code-to-token request to retrieve refresh token

Hybrid flow details

  • It addresses the implicit flow limitation with no refresh token
  • Still has security implications (initial tokens in URL fragment)

Keycloak and hybrid flow

  • Requires both 'standard' and 'implicit' flags enabled for client
  • Use parameter to keycloak.init like:
  • keycloak.init({ flow: 'hybrid' })

response_mode parameter

  • Optional parameter used in Authorization Request
  • Supported in OpenID Connect 1 specs
  • Valid values:
    • query
    • - authorization response will send parameters in URL query
    • fragment
    • - authorization response will send parameters in URL fragment
    • form_post
    • - authorization response will be POST request instead of GET. Params in the body

Authorization code

  • Authorization Code flow uses 'query' mode by default
  • Query mode is needed for server applications
  • Javascript applications don't need query
  • They need code to be available just in browser side ( in keycloak.js )
  • keycloak.js now uses 'fragment' mode by default even for authorization code flow
  • fragment is safer. Code parameter not send to client application
  • Hence keycloak.js login requests now use parameter in login request: response_mode=fragment
  • Switch keycloak.js to fallback to query with init parameter:
  • keycloak.init({ responseMode: 'query' })

Implicit and Hybrid flow

  • Implicit and hybrid are using 'fragment' by default
  • Query mode is not even allowed (per specs)

keycloak.js default behaviour

  • Still using Authorization Code flow like before
  • Using fragment response mode now
  • A bit safer than before. Code is not send to the client application anymore