I'm trying implement a browser-based login for a native mobile app from an existing Single Page Application. It uses WebView
to render the SPA and it uses Keycloak OIDC as its Identity Provider.
The SPA and IdP is located in completely different domain and authentication is done by redirecting to the SPA domain after a successful login and retrieving the active session (cookie) from IdP domain in one of the SPA's server. The authentication check is achieved by using keycloak middleware which I believe is the protect.js
Summary:
Based from the spec, the authorization should happen in the browser / in-app browser, and authorization code must be passed via custom URL scheme. Having that in mind, the SPA that resides in the WebView
of native mobile app will never establish a session from IdP's domain since this will be delegated from the browser which is on a different process and obviously using a different cookie store than on WebView
in the mobile app, which makes our existing solution to break because it is relying on the IdP's domain cookie.
The issue I described above can be mitigated by cutting the reliance on IdP's session and by managing the SPA's own session, which basically means storing the token persistently that can be obtained from the IdP (which the current solution doesn't do).
(I don't want to detail much of the solution since I just want to focus first on the concept of storing the token. I think it's better for me to put this in a separate discussion if someone is interested)
If you're using the default Keycloak middleware in your server and use keycloak.protect() for protecting endpoints, it checks on the request.session['keycloak-token']
which contains the access_token
that was created during the token request after user login. If this exist and valid, it means user will not be redirected to Keycloak login page.
KEYCLOAK_SESSION, KEYCLOAK_SESSION_LEGACY, ...
, a session will automatically be created.When using the keycloak-connect
client adapters, you can access protected resources if the user agent (browser/app), has a valid session in your server OR if the request contains valid Authorization
header.
Authorization
header and use access_token
which the keycloak.protect() also accepts. You can obtain this token in a standard way using Chrome Custom Tabs
for Android and ASWebAuthenticationSession
for iOS. You can also use AppAuth
(iOS, Android) to lessen your work.refresh_token
and access_token
from native mobile and inject this in the HTTP request of WebView
if possible.access_token
validity and use refresh_token
to request for a new one. If requesting for a new one fails, i.e., the authorization server verifies it's not valid anymore, that means users would need to re login again.By using the standard solution I have proposed above, you should not need to create a band-aid solution for your issue. Hope this helps anyone that have faced similar issue.