Subject: [OAUTH-WG] Implicit Grant Flow for authentication on both Client UI and Back End by OIDC id_token verification

From: Sergey Ponomarev <[email-masked]>
Date: Wed, 19 Jan 2022 00:53:52 +0200

Hello OAuth experts,

I developed a new Grant Flow based on the Implicit Grant Flow and OIDC
and I would like to ask for it's review.
I hope it's safe, but maybe I missed something. I'll appreciate any feedback.

The Implicit grant flow was intended for authorising clients which
can't store the `client_secret` like SPA.
It was considered not very safe and some Auth Services like GitHub
don't even support it.
OIDC added `id_token` which is a signed JWT (JWS) that contains user info.
If we just need for authentication it's now possible to request the
only `response_type=id_token` i.e. we aren't interested in getting the
`access_token`.
Anybody can verify that the token was issued by the Auth Server and it
wasn't changed.
We may also ask to include our own `nonce` into the `id_token` and
thus we may protect from reusing the `id_token` twice.
This gives us an ability to use the `id_token` for server validation.
To explain the flow let's take for example a Google:
1. On UI a User press Login button
2. UI asks a server for the `nonce`, server generates it, stores and
returns to UI. For example `gNNMgg`.
3. Now UI redirects a User Agent to Auth Server with the received
`nonce`, a random `state` and `response_type=id_token`
4. The User authorises the Client (app) on the Auth Service and
redirects back to the Client UI and an `id_token` is passed in a hash
`#` part of URL.
5. The UI checks that `state` is the same as it generated on step 3.
6. The UI now has the User details but Server does not. So the UI
sends the received `id_token` to a Client Server.
7. The Client Server verifies the `id_token` signature with a public
JWKS of the Auth Server.
8. To avoid submitting someone else's stolen `id_token` the Client
Server also verifies that its own generated `nonce` is the same as
included into the `id_token`.

The key advantage of the flow is that the Client Server doesn't have
to perform a side channel request to the Auth Server as it needs in
the Authorization Code flow.
This not only improves performance but also allows to decouple Client
Server from Auth Service.
For example the Client Server can't connect to the Auth Service
because of connectivity problems.
Or if the AS is blocked in the Client Server country (e.g. Yandex and
VK.com in Ukraine, Google in China, Twitter in Nigeria etc.).
Another reason if the Client Server wants to hide its IP from the Auth
Service e.g. this a Tor Hidden Service with .onion domain.
The Client Server anyway has to periodically fetch the JWKS of the AS
but this can be done by a secure channel (e.g. by the same Tor
network).
Now it's possible to block any outgoing connections from the Client
Server that significantly improves safety.

Could you please confirm that this is a correct flow and I didn't miss anything?

The PoC demo https://stokito.com/auth.html Click on Login with Google
The PoC sources https://github.com/yurt-page/cgi-oauth

Thank you in advance,
Sergey

---

From: David Waite <[email-masked]>
Date: Tue, 18 Jan 2022 17:38:19 -0700

Sent from my iPhone

> On Jan 18, 2022, at 3:54 PM, Sergey Ponomarev <[email-masked]> wrote:
<snip>
> can't store the `client_secret` like SPA.

It is orthogonal to that, you can do code flow without client secrets as well. OAuth was released at a time of much simpler JavaScript development, and before standardization of CORS. Implicit was more of an implementation simplicity trade off for JavaScript clients. 

> OIDC added `id_token` which is a signed JWT (JWS) that contains user info.

The id_token is a message from the OP/AS to the client about the end user - their subject identifier and other authentication information. other user claims are sometimes bundled in by implementations, such as when the client is not asking for an access token and thus will not be able to hit the user info endpoint. 

> only `response_type=id_token` i.e. we aren't interested in getting the

Yes. 

> Anybody can verify that the token was issued by the Auth Server and it

If the client has a confidential cryptographic key the id_token may be encrypted. But 99.9% of the time, yes. 

> thus we may protect from reusing the `id_token` twice.

The nonce claim is required for implicit, and really should be mandatory for all cases where the id_token is in a front channel. The reuse restriction is really one of having the authentication protocol be interactive. 

> This gives us an ability to use the `id_token` for server validation.

The goal is for server validation of id_tokens. A JavaScript client has limited power in making security decisions, e.g. restricting user access to data in the local browser IndexedDB isn’t really possible. 

Browser consumption of id_tokens is really a demo-level construct. You could potentially use it to pull values out and personalize the page AKA “Welcome, <name>” or attempt to lock down the presentation layer to prevent casual drive-by information leaking, but there’s no reason for the server to trust an assertion from a JavaScript client about the user. 

> To explain the flow let's take for example a Google:
<snip steps>

These are correct. For implicit, the state parameter is used to prevent some cross browser issues such as XSRF attacks. Guidance for code flow is to use PKCE, so state can actually be used “just” for application state, such as what the user was trying to do before authentication was required. 

> Server from Auth Service.

There are ramifications of this approach, such as losing access to other OAuth extensions which are only defined for code flow, and potentially having PII flow through the browser. You also lose the ability to potentially get new id_tokens (extending the session) through refresh, since there’s no chance for a refresh token. Finally, it propagates implicit flow, which has an interoperability impact. 

Generally my advice is “use code unless you can’t.”

> VK.com in Ukraine, Google in China, Twitter in Nigeria etc.).

Generally these sorts of connectivity issues and clocks will impact the implicit channel as well - they won’t block Google’s auth endpoint, they’ll block Google. 

> Service e.g. this a Tor Hidden Service with .onion domain.

The call for the code grant can also be made through the same VPN-style interfaces. 

It is more of an issue when the client has different networking access, such as an employee using an on-prem OIDC OP to get access to a hosted RP product. The JavaScript can interact within the firewall, but operations has not exposed the token endpoint properly. <snip>

> Server that significantly improves safety.

It does, at the loss of other functionality and a change in security requirements and properties between code and implicit clients.

-DW

---

From: Warren Parad <[email-masked]>
Date: Wed, 19 Jan 2022 12:39:36 +0100

Sergey, you probably want to look into using *auth code + PKCE* flow. There
is a standardized formal flow for this, and it will resolve your
concerns as well as remove some of the pitfalls with your current approach.
What you have implemented is very similar, but misses on some key
optimizations such as not needing a backend service, requiring the
utilization of the nonce, incorrect usage of the *id_token* to name a few.

- Warren

Warren Parad

Founder, CTO
Secure your user data with IAM authorization as a service. Implement
Authress <https://authress.io/>.

On Wed, Jan 19, 2022 at 1:38 AM David Waite <david=
[email-masked]> wrote:

> It is orthogonal to that, you can do code flow without client secrets as
> well. OAuth was released at a time of much simpler JavaScript development,
> and before standardization of CORS. Implicit was more of an implementation
> simplicity trade off for JavaScript clients.
>
> The id_token is a message from the OP/AS to the client about the end user
> - their subject identifier and other authentication information. other user
> claims are sometimes bundled in by implementations, such as when the client
> is not asking for an access token and thus will not be able to hit the user
> info endpoint.
>
> The nonce claim is required for implicit, and really should be mandatory
> for all cases where the id_token is in a front channel. The reuse
> restriction is really one of having the authentication protocol be
> interactive.
>
> The goal is for server validation of id_tokens. A JavaScript client has
> limited power in making security decisions, e.g. restricting user access to
> data in the local browser IndexedDB isn’t really possible.
>
> Browser consumption of id_tokens is really a demo-level construct. You
> could potentially use it to pull values out and personalize the page AKA
> “Welcome, <name>” or attempt to lock down the presentation layer to prevent
> casual drive-by information leaking, but there’s no reason for the server
> to trust an assertion from a JavaScript client about the user.
>
> These are correct. For implicit, the state parameter is used to prevent
> some cross browser issues such as XSRF attacks. Guidance for code flow is
> to use PKCE, so state can actually be used “just” for application state,
> such as what the user was trying to do before authentication was required.
>
> There are ramifications of this approach, such as losing access to other
> OAuth extensions which are only defined for code flow, and potentially
> having PII flow through the browser. You also lose the ability to
> potentially get new id_tokens (extending the session) through refresh,
> since there’s no chance for a refresh token. Finally, it propagates
> implicit flow, which has an interoperability impact.
>
> Generally these sorts of connectivity issues and clocks will impact the
> implicit channel as well - they won’t block Google’s auth endpoint, they’ll
> block Google.
>
> It is more of an issue when the client has different networking access,
> such as an employee using an on-prem OIDC OP to get access to a hosted RP
> product. The JavaScript can interact within the firewall, but operations
> has not exposed the token endpoint properly. <snip>
>
> It does, at the loss of other functionality and a change in security
> requirements and properties between code and implicit clients.
>
> -DW
> _______________________________________________
> OAuth mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/oauth
>