4D-Technologies / openidconnect_flutter

Complete Flutter OpenIdConnect Library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support implicit grant flow

fdaugs opened this issue · comments

Currently this package does not work with Google (e.g. Google Workspace) as IdP for a web app, because accounts.google.com only supports the authorization code flow with PKCE for mobile clients (iOS and Android). If you create an OAuth-ClientId of type "Web-Application" and configure the plugin with:

final configuration = await OpenIdConnect.getConfiguration(
      '${request.issuer}/.well-known/openid-configuration',
);

final result = await OpenIdConnect.authorizeInteractive(
  context: request.context,
  title: "Login",
  request: await InteractiveAuthorizationRequest.create(
    clientId: clientId, // Client ID optained from google cloud console
    redirectUrl: 'https://example.com/callback', // URL of my flutter app
    scopes: request.scopes,
    configuration: configuration
  ),
);

The request fails with an error, that grant_type is an unsupported parameter. If I alter the code of this plugin to omit the grant_type parameter the, login screen is shown correctly but the code exchange on the token endpoint fails, because it expects a Client ID.

grant_type implicit is intentionally not supported because implicit flow is depreciated and recommended to not be used by the OpenIdConnect governing authority. It must use PKCE .

Note that authorization code flow is now supported by google.

https://developers.google.com/assistant/identity

Hi @jhancock4d,

thanks for your response! You're right implicit flow is deprecated but sadly google does not yet support the auth code flow with PKCE. So this would require me to store the client secret in a js client for example: https://developers.google.com/identity/openid-connect/openid-connect

I think this is why they still recommend the implicit flow for javascript clients: https://developers.google.com/identity/protocols/oauth2/javascript-implicit-flow

If you have any idea on how to use PKCE with google your help would be greatly appreciated!

I am planning on adding support for implicit flow for the reasons you have mentioned @fdaugs

Ah awesome! Thank you 🙏

Please do not. Implicit flow is dead and insecure and should never be used for anything.

Yes, google requires you to pass the client secret when using PKCE, but it doesn't make it any less secure in a public environment. It's still MORE secure than implicit flow without a client secret.

According to the docs, just setup a separate web client id and secret with PKCE and use it per their docs.

@jhancock4d I think the security part should be left to the Identity Provider, not the Relying Party to decide.
we should offer support for all possible flows, and if some of them get deprecated, we just warn the users in the docs

Depreciated means depreciated as in not supported for any new uses. You don't add stuff that is broken to an existing library by definition. If someone wants Google auth, there is an entire package that Google provides for flutter that does it.

If you're using just google, you should be using their library that just works.

If you're not using just google and you're doing multiple different ways of SSO, then you should be using your own Idp and doing pass through to those providers as necessary and capturing the auth information on the way back and maintaining that information in your Idp per the best practices for OpenIdConnect.

Thus there is no case where there is any reason at all to use this library and add depreciated and recommended not to use functionality to the spec.

And if someone insists on ignoring those best practices, there is a work around: PKCE with Client Secret which is still more secure than implicit flow so this isn't even blocking.

actually one might argue otherwise.
capturing client secret from source is way easier than man in the middle attack, you just right click -> view page source and voila, you can impersonate the RP.
on the other hand, other libraries that removed support for implicit flow are also suffering from this problem authts/oidc-client-ts#152 (comment)

A lot of developers want full control of the Auth UI, and I believe having a single library that can adapt to all the available IdP flows without switching between different SDKs is better

e.g.: Gitlab's Auth UI
image

However, I can understand why you don't want to support implicit flow, and it's ok with me

  1. Gitlab is proxying the SSO through their own Idp per best practices. You can tell this just by hovering over the links. If they weren't proxying through their own Idp those links would be directly to google. They are not, they're to GitLab and those links even look very similar to what you see in the best practices on this topic by Microsoft and C# for multiple SSO.
  2. A client secret getting out with PKCE is immaterial. Implicit flow doesn't have one at all, and doesn't verify the round trip. You're equating the client secret of PKCE with the client secret of a client flow that is secured. They're not the same. Client secret is an added benefit but can't be treated as secure even in a secured client flow either which is why PKCE should be used on secure clients as well. Just don't use the same client id and secret for web as you do for your other apps (in fact you should have a separate one for every app, which is how this library is setup.)

I.e. there is both no reason to have a client secret on a browser in PKCE and google shouldn't be requiring it, but also, it doesn't matter that there is a client secret that is public because it makes the flow no less secure on the given platform (browser) than any other alternative and because PKCE validates the flow, it's massively more secure than implicit in all cases even with exposed client secret. So, the correct answer is to include your client secret to placate google and then not care about it because you're still better off.

And again: If you're just doing google, then just do google with their library. If you're doing many SSOs then you should be doing as Gitlab and literally every other service that does SSO does and proxy the result through your own IdP. They are not sending users directly to the 3rd party and then blindly trusting the JWT tokens that come back for multiple reasons:

  1. JWT is not secure in and of itself. There are tons of attack vectors.
  2. You can't trust the contents of the JWT even if signed and encrypted. There are tons of attack vectors in the wild.
  3. The JWT may or may not have the information you need from your server. I.e. it is always better to issue a JWT from your server that has the user id that is the primary clustered index of your user table for look up then having to lookup by an email address that you'd probably have to use as the lowest common denominator otherwise because the PK will be smaller, the index vastly faster and the index vastly smaller too.
  4. The user's email address (lowest common denominator lookup) can easily be different than you have in your system. Now you have to create a map for no good reason between systems anyhow.
  5. The proper contents of an auth jwt token is the User_id and an encrypted hash from the server that expires with the token AND NOTHING ELSE. Then your Idp looks up the User_id and the encrypted hash and the expiry of the token, preferably cached using redis or similar and validates the encrypted hash that only it can decode. This means that at best, the token could be stolen for the life of the token and nothing more.

This is well covered and documented in C# server side as a small example with proper flows that should be used.

I think we can agree, that Google is the Problem here :D Even Microsoft supports PKCE. The weird thing is, that they support it for mobile clients: https://developers.google.com/identity/protocols/oauth2/native-app#step1-code-verifier

Using the client secret approach is not an option for me, so I won't support Google Login...

I think we can agree, that Google is the Problem here :D Even Microsoft supports PKCE. The weird thing is, that they support it for mobile clients: https://developers.google.com/identity/protocols/oauth2/native-app#step1-code-verifier

Using the client secret approach is not an option for me, so I won't support Google Login...

Why isn't client secret separate for web an option? There is 0 more risk than your request for implicit flow. In fact vastly less. Just don't share the same client secret between platforms.

I will look into it. Thanks!