appsup-dart / openid_client

Library for working with OpenID Connect and implementing clients.
BSD 3-Clause "New" or "Revised" License
90 stars 118 forks source link

How to avoid redirect to Keycloak on page reload? #102

Closed adrian-moisa closed 6 months ago

adrian-moisa commented 1 year ago

I've managed to implement the OIDC authorisation PKCE flow on Flutter web using the following tutorial: https://medium.com/@rangika123.kanchana/keycloak-integration-for-flutter-web-using-openid-client-with-authorization-code-flow-489afeac6e9f . Overall everything seems to be working fine. Silent refresh of the token during the same session works just fine. Now I'm struggling with the following problem:

So all in all, my question is, can I avoid the mandatory keycloak redirect safely? Or is storing refresh tokens in local storage (even with token rotation) a bad idea and should be avoided. If so is there any way at all to avoid the redirect? Having the app loaded and intialised twice at each page refresh is rather annoying. Especially during the frequent hot reloads in development. Any advice would be much appreciated. A code sample even more. Cheers!

rbellens commented 1 year ago

First of all, I'm no specialist in keycloak, nor in security. This package only implements openid flows, the storage of credentials is not within the scope of this package.

Although, it is sensitive for xss attacks, I believe that many apps do store the refresh token in local storage. I think, you could also use http-only cookies, which are not readable by scripts and therefore not sensitive for xss attacks.

You could also use a technique called silent sign-in. This would imply doing the redirect in an invisible iframe. The page that loads after successful sign-in should then be able to communicate with the parent page and send the credentials.

adrian-moisa commented 1 year ago

I'll have to research more the silent sign in how it is done. It seems that this is the way forward. Also http-only cookies could help on this path. Thank you for the indications. If you don't mind I'll keep it open in case there are other users that can provide some more indications.

alex27riva commented 7 months ago

I've managed to implement the OIDC authorisation PKCE flow on Flutter web using the following tutorial: https://medium.com/@rangika123.kanchana/keycloak-integration-for-flutter-web-using-openid-client-with-authorization-code-flow-489afeac6e9f . Overall everything seems to be working fine. Silent refresh of the token during the same session works just fine.

Hi Adrian, I'm trying to implement the same thing. Do you still have a code example around?

adrian-moisa commented 6 months ago

tbh I wouldn't share the sample. It's a complete mess. I mean it works but it overrides the web implementation of openid_client because they use implicit as far as I can understand their code. Implicit is discouraged. I wanted PKCE on web as well. They do it only on mobile. Also the current setup ends up doing 2 loads of flutter bundle. Which is a massive slow down. Once to load the lib, then redirect then to start the app logged in. I want to implement an inline mask login to get rid of this double login. Plus, right now the web version does not have token refresh. One more problem. Overall I see that I have to do so much patching to this lib that I'm already thinking that maybe I will go with some vanilla oauth lib and just follow the general recipe to login. By now I have a slightly better understanding of the entire ouath thing and I can venture into doing something cleaner with less clutter.

alex27riva commented 6 months ago

tbh I wouldn't share the sample. It's a complete mess. I mean it works but it overrides the web implementation of openid_client because they use implicit as far as I can understand their code. Implicit is discouraged. I wanted PKCE on web as well. They do it only on mobile. Also the current setup ends up doing 2 loads of flutter bundle. Which is a massive slow down. Once to load the lib, then redirect then to start the app logged in. I want to implement an inline mask login to get rid of this double login. Plus, right now the web version does not have token refresh. One more problem. Overall I see that I have to do so much patching to this lib that I'm already thinking that maybe I will go with some vanilla oauth lib and just follow the general recipe to login. By now I have a slightly better understanding of the entire ouath thing and I can venture into doing something cleaner with less clutter.

Hi Adrian, thanks for your reply. I did not know that the web version of the library used Implicit Flow. So I am passing the “Code Verifier” and “Code Challenge” but it is not actually used? In addition, I also have the problem with double login. I have to double click the “login” button that calls the authenticateWeb() function to log in. I need to find a solution.

adrian-moisa commented 6 months ago

@alex27riva have you progressed on this issue? I'm currently researching flutter_web_auth_2 but I expect the double loading problem there as well. At the moment I'm thinking to write some logic in index.html to check if there is anything stored in local storage related to access tokens. If not straight away redirect to IAM login. Another thing that I am looking for is silent refresh of the token. Since I did my own web Authenticator implementation that uses authorisation flow it does not have the token refresh technique. I might as well implement a lib that has them both.

Another solution I was thinking of was to write an embedded login. But the more I read on the web the more I understand that embedded login can't be easily implemented without some major security problems. Apparently the redirect is the lasy way to ensure average Joe devs like us can't duck it up really bad. I've seen that Okta provides an embedded client lib for js SPAs. So I get proof this is possible for people who know how to do it.

alex27riva commented 5 months ago

@alex27riva have you progressed on this issue? I'm currently researching flutter_web_auth_2 but I expect the double loading problem there as well. At the moment I'm thinking to write some logic in index.html to check if there is anything stored in local storage related to access tokens. If not straight away redirect to IAM login. Another thing that I am looking for is silent refresh of the token. Since I did my own web Authenticator implementation that uses authorisation flow it does not have the token refresh technique. I might as well implement a lib that has them both.

Another solution I was thinking of was to write an embedded login. But the more I read on the web the more I understand that embedded login can't be easily implemented without some major security problems. Apparently the redirect is the lasy way to ensure average Joe devs like us can't duck it up really bad. I've seen that Okta provides an embedded client lib for js SPAs. So I get proof this is possible for people who know how to do it.

Hi Adrian, I ditched openid_client library and I migrated to oidc package. Now the login and logout works perfectly and I completed my Oauth2 project.

adrian-moisa commented 5 months ago

Hi @alex27riva. Good to hear you making progress. I also moved away from openid_client. I use flutter_web_auth_2. Same experience, now I get a far more cleaner implementation. To be fair to openid_client also my understanding of oauth2 has improved and I was able to code cleaner. However, there are some notable improvements with the new lib. It has support for custom tabs and most importantly, it communicates back from the login mask via activity and intent messages. No longer using session storage to pass the access token. Safe travels ahead!