Using Google OIDC with code flow and PKCE - oauth-2.0

after trial and error it seems to me that Google OIDC does not support the code flow without supplying the client secret:
https://developers.google.com/identity/protocols/oauth2/native-app#exchange-authorization-code
According to the latest best practices for SPAs (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-13), code flow + PKCE is the recommended way to handle authentication. Is anyone aware of any trick required to make Google's code flow accept the code_challenge rather than the client_secret? Perhaps a dummy secret?

As of August 2020 the best practices document cited is still in draft and being activly updated - head revision here: https://datatracker.ietf.org/doc/draft-ietf-oauth-security-topics/. Googles' OAuth2 implementation has not yet applied the "work in progress" recomendation of PKCE being applied to web applications. SPAs are still directed to use the implicit flow in Googles' online documentation: https://developers.google.com/identity/protocols/oauth2/javascript-implicit-flow).
The standard for PKCE (https://www.rfc-editor.org/rfc/rfc7636) details that it was developed as a mitigation for authorisation code interception attacks found on mobile platforms and was originally recommended for implementation by native clients. Google's documentation for "Mobile and Desktop apps" does direct developers to use a PKCE Authorization Code flow. Clients using Google Android, iOS or windows store credential types with PKCE may omit the client_secret (see the note on the refresh token parameter table - and confirmed by Cristiano).
It is now recognised that PKCE eliminates the need for any public clients to store a client secret, and as such can be used to deprecate the implicit flow which always had the flaw of including returned access and identity tokens in a redirect URI. https://developer.okta.com/blog/2019/05/01/is-the-oauth-implicit-flow-dead.
The draft IETF document states in section 2.1.1 that this recognition is likely to become a published standard.
Hopefully Google will update its implementation to remove the requirement for a client_secret for a PKCE token request when the best practices becomes accepted. In the meantime it seems we have no choice but to continue writing SPAs using the implicit flow.

A good alternative IMHO consists in using Keycloak as IDP and then adding Google to the delegate identity providers of your Keycloak instance (and then Facebook and then any other idp if required). Keycloak implements the PKCE flow or whatever flow in the Oauth 2 RFCs in a reliable way. That means you need a hosted instance of Keycloak though.

Well, I'm using openId Connect authorization code with pkce without using client_secret in an android app using this lib: https://github.com/openid/AppAuth-Android.
I just had to ensure that the custom scheme was set using the app's package name from the manifest and use it to register the android credential on google console.

Related

Which one is more safe for the web app with server, PKCE Flow or standard Authorization Code Flow?

It is known that PKCE Flow is good solution for SPA or native app, rather than the standard Authorization Code Flow.
However for the web app with server ("confidential client" as defined in RFC 6749), which one is more safe?
As mentioned in this post, "PKCE is all about verifying that the client that initiated the initial authentication request is also the same that uses the authorization code to get the real tokens."
How can Authorization Code Flow with PKCE be more secure than Authorization Code Flow without client_secret
However PKCE cannot involve client credentials (client_secret), which is used in the Authorization Code Flow to make sure the requester is the authenticate client.
So seems the standard Authorization Code Flow is more safe than PKCE Flow, for the web app with server (confidential client).
Nor sure is this unstanderding correct? Because we can see in the latest oauth2.1 draft it seems prefer PKCE, as it says "PKCE is required for all OAuth clients using the authorization code flow".
https://oauth.net/2.1/
Update on May-13 2021: Actually the oauth 2.1 suggests authorization code flow plus PKCE parameters, not using PKCE instead of authorization code flow.
Amazon and Microsoft have followed the suggestion in their spec.
https://developer.amazon.com/zh/docs/login-with-amazon/authorization-code-grant.html
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow
Thanks all
You can refer to this document>> https://fusionauth.io/blog/2020/04/15/whats-new-in-oauth-2-1 and references for more details.
The answer to your question is >> PKCE is safer than a normal Authorization code grant or any other grant.

OAuth2 authorization interface using KeyCloak

I'm trying to use KeyCloak as identity provider service for 3rd party applications support. The idea is to register the client application in KeyCloak, trusted clients will not require this authorization approval, but there should be "untrusted" client flow, e.g. display user authorization interface as specified in OAuth 2.0 specification.
From what I see in the docs, they have pretty good fine-grained authorization mechanisms which can be used for that on the backend. However I don't see any way to provide authorization screen for /authorize endpoint as shown above.
Maybe this can be custom created SPI or something else which can be used for implementing this to move further. Any ideas of how this can be implemented in KeyCloak? Are there any built-in features which can be reused or custom way implementation?
In Keycloak you can turn on the Consent Required switch per client (see client settings in admin console).
After successful authentication this will bring up a confirmation page similar to your example.

oauth2 openid connect javascript (electron) desktop application

What is the correct oauth2 flow for a desktop application? Besides a desktop application I have a SPA Web GUI which does use the Implicit flow. There it does not matters if the client Redirects after 3600s to the IdP to issue a new Access token.
But the desktop application needs to be running 24/7 or could be running 24/7. So it needs to automatically refresh the access token via a refresh_token. But since the implicit flow does not provide refresh tokens it is probably the wrong flow for a desktop app, isn't it?
I guess I need the auth code flow, which does provide a refresh_token. But authentication requests needs a redirect_uri. Let's say I want to use Google as my openid provider. With google it looks like I can't register client credentials with a custom URI scheme (https://developers.google.com/identity/protocols/OpenIDConnect). What does work is to register for example http://localhost:9300, which theoretically could be handled by the app.
A
Whats the correct oauth2 flow for a desktop app to receive a refresh_token?
B
Can I catch the redirect_uri via a custom URI scheme without using the implicit flow (Google IdP)? It is way easier to listen for a custom uri scheme than listening on a local tcp port.
C
This is more a general question. Usually desktop apps are public apps, so I should not include client_secret right? So the only flow which would be left is the implicit flow. But how can I renew access tokens according to specs without bother the desktop user every 3600s?
In my case I could publish the app locally so not public, but how is it for a public app?
A - Authorization Code Grant
B - Not sure here, You can register a Custom URI Scheme
C - Not enough information provided.
Are you using the AppAuth libraries? If so you SHOULD use PKCE and then additional security measures for the refresh token should not be necessary, on the assumption that the client never sends the refresh token with anyone other than the IDP over a secure connection.
Does this help?
A: Yes use the code grant
B: yes use a custom scheme. In your case you should use the reverse of your client ID. e.g. com.googleusercontent.apps.123 is the reverse DNS notation of the client ID. Register your client as "Other" in the Google developer console.
C: Yes, it should not include the client secret. That is why you don't need to send the secret for native clients ("Other") when exchanging the code for a refresh token. Just leave that field blank and it'll work.
As suggested by jwilleke, please use an AppAuth library if it is available for your use case as it'll also handle some of the security issues (PKCE).
For native apps (Desktop), you can follow OAuth 2.0 for Native Apps. But this is still under review and you can refer the latest draft from provided link.
With this flow, you can use authorisation code flow to obtain both access token and a refresh token. Refresh tokens should solve the UX related issue when it comes to extended app usage (24/7 and beyond).
According to this working document, there are strict guidelines on client authentication. Section 8.5 discuss about them. As it says client credentials are not recommended
For this
reason, and those stated in Section 5.3.1 of [RFC6819], it is NOT
RECOMMENDED for authorization servers to require client
authentication of public native apps clients using a shared secret
Also as nvnagr has mentioned in his answer, PKCE [RFC7636] is a must to have for native public clients.

How could we use GitHub account as an AWS Cognito Identity provider?

By reading Cognito Identity Provider document, I understand that it looks like it provides out-of-box integration with Facebook / Google / Twitter as Identity Providers.
My application is a developer focused application so I would like enable users sign-up/sign-in with their Github account besides the above Identity Provider's accounts. Is that possible?
If possible, how much extra work (comparing the out-of-box Facebook/Google social sign-up feature) I need to do?
Since first writing this answer, I implemented and published a project that provides a wrapper for Cognito to talk to GitHub. It comes with a SAM/cloudformation deploy script, so you can create a CloudFormation stack that provides the wrapper very easily.
So, OpenID Connect is built on top of OAuth2.0. It's an extension - in OpenID Connect, the OAuth endpoints are there (with one or two extensions or changes), plus some new endpoints.
My understanding from reading the Cognito documentation and the relevant bits of the OpenID Connect and OAuth2.0 specs is that Cognito only uses four of the OpenID endpoints - Authorization, token, userinfo and jwks. You can specify each endpoint separately when configuring an OpenID Connect provider in Cognito. This means it is possible to provide OpenID Connect for github by implementing these endpoints.
Here's a rough plan for implementation:
Authorization: In the spec, this looks to be the same as the OAuth2.0 endpoint (plus some additional parameters that I don't think are relevant to using github as an identity provider). I think you could:
Use the github Auth URL: https://github.com/login/oauth/authorize
Set your GitHub OAuth app to redirect to https://<your_cognito_domain>/oauth2/idpresponse
For the other endpoints, you'll have to roll them yourselves:
Token: This is used to get the access and ID tokens - using a code returned by the authorization callback. It looks the same as the OAuth2.0 endpoint, but also returns an idToken. It looks possible to make an implementation that passes through the code to github's token endpoint (https://github.com/login/oauth/access_token) to get the accessToken, and then generates an idToken, signed with your own private key.
UserInfo: This doesn't exist at all in OAuth2.0, but I think that much of the contents could be filled in with requests to the /user github endpoints (since at this point the request contains the authenticated access_token). Incidentally, this is the reason that there's no open source shim to wrap OAuth2.0 with OpenID connect - OpenID connect's primary contribution is a standardised way of communicating user data - and since OAuth doesn't have a standardised way to do this, we have to write a custom one specific to GitHub (or any other OAuth-only provider we wanted to use for federation).
JWKS: This is the JSON Web Key Set document containing the public key(s) that can be used to verify the tokens generated by the token endpoint. It could be a flat file.
I have implemented the above, and the approach works. I open-sourced the project here.
Unfortunately it's not possible. Cognito Federated Identities can support any OIDC Identity Provider but OAuth2.0 spec does not give that flexibility, so there's no easy way to achieve this unless we add special support for Github.

Does Smartsheet API support standard OAuth 2.0 for third-party auth?

I am working on a web app which will need to implement the three-legged OAuth 2.0 flow. The Smartsheet API docs http://smartsheet.com/developers/api-documentation say that the API supports standard OAuth 2.0 flow. On closer inspection, however, I see that access and refresh token management operations require that instead of sending over the client secret (which appears to be the standard behavior in other APIs), I have to send over a hash, quoting "SHA-256 hash of your client secret concatenated with a pipe and the authorization code. The client_secret is never sent with the request."
Given that this is different from the standard OAuth 2.0 flow, does Smartsheet API support the standard behavior?
Passing the secret in the clear - on the URL - is not supporterd. The flow described in the documentation is an OAuth2 flow, though it is admittedly not the common flow that is most generally used among SaaS vendors. The OAuth2 spec allows for extensions to the token endpoint to accommodate the security requirements of the authorization server, and the SHA256 hash is one such extension.

Resources