> On Nov 8, 2018, at 4:19 AM, Tomek Stojecki 
> <tstojecki=40yahoo....@dmarc.ietf.org> wrote:
> 
> Thanks for putting this together Aaron. 
> 
> Having read through the document, I am not as convinced that there is enough 
> of a benefit of Authorization Code + PKCE vs Implict Flow for SPAs.
> 
> In section 7.8. the document outlines the Implicit flow disadvantages as 
> following:
> 
> "- OAuth 2.0 provides no mechanism for a client to verify that an access 
> token was issued to it, which could lead to misuse and possible impersonation 
> attacks if a malicious party hands off an access token it retrieved through 
> some other means to the client."
> 
> If you use Code + PKCE with no client secret (public client) as it is being 
> advocated, you can't verify the client either. PKCE is not for authenticating 
> the client, it is there to provide a mechanism to verify inter-app 
> communication, which occurs between a browser and a native app. There is no 
> inter-app communication in implicit (everything stays in the browser), so no 
> need for PKCE.

Use of a fixed set of uniquely resolvable redirect URIs (e.g. not localhost, 
not arbitrarily registrable custom URI schemes) does provide an addressable 
channel to the public client for codes and implicit tokens. I should not be 
able to make a client that can reuses the public identifier as a third party, 
because I cannot catch the response URL from the authorization endpoint.

The difference is with implicit, the first party client cannot verify the 
tokens were meant for the client (or really even that they came from the AS). 
With code, you are contacting the AS and doing an exchange based on the code 
and your public client identifier.

In the sense of pure OAuth, where no authentication or additional authorization 
decisions are made based on the access token, the issuer and audience client 
could be checked via an introspection endpoint - but if you are using pure 
OAuth and not relying on things like CORS restrictions for your security model, 
it shouldn’t matter.

For OpenID Connect and cases where you are going beyond a pure authorization 
model (perhaps by having API access restricted by CORS), this sort of check is 
important. You could trust clients to explicitly check by looking in an 
id_token (when available) or calling an introspection endpoint, or you could 
have this check happen as part of normal flow by using code flow.

PCKE does not resolve any known code injection attacks for SPA public clients. 
Recommending administrators require PKCE does allow them to start to make a 
single coherent policy for public clients.

A consistent policy also helps in SPA/native app crossover cases. For examples, 
a javascript app could be published as a native app via wrapping in a 
Cordova-style toolset, or by sharing a significant amount of code using a 
React-native style toolset. Both the SPA and native app could then share 
handling links depending on native app installation due to universal/app link 
features of the operating systems. For this reason, there was a definite effort 
to propose best practices that overlapped with the native app BCP.

It is also worth noting that since the SPA and native app could share the same 
client identifier and redirect handling (via universal links), you *could* have 
code injection, but it would be between multiple first-party apps.

> "- Supporting the implicit flow requires additional code, more upkeep and 
> understanding of the related security considerations, while limiting the 
> authorization server to just the authorization code flow simplifies the 
> implementation."
> 
> This is subjective and can be easily argued the other way. I think one of the 
> main selling points behind implicit was its simplicity. It is hard to argue 
> (putting libraries aside) that making one redirect (implicit) requires more 
> code, work, etc.. than making a redirect and at least two additional calls in 
> order to get AT (plus CORS on AS side).

The implicit flow is only simpler for clients until they have to get a new 
access token. Typically then you need a different set of OAuth code to request 
a new token in the background via a hidden iframe, failing back to temporarily 
leaving the app via top-level redirect. There are also cases where the safari 
browser detects this cross-domain iframe bouncing as a tracker and segments any 
AS cookies/storage per client site.

It is more work for the AS to support both. You may also wind up having 
different security models for the two different public client flows. In 
particular, you may find yourself as an AS policy setter wanting to have longer 
lived sessions for implicit clients which do not have refresh tokens to extend 
access token validity in the background. For this reason, you may also decide 
implicit clients cannot get access to the same scopes that a code client can. 

There are also gotchas people are not used to in implicit, such as fragment 
identifiers being preserved on redirects.

For OpenID Connect, getting the id_token on a back-end call means that there is 
still transport-level security of the value if clients ignore the signature. 
Again, you could trust your clients to explicitly add signature verification 
code for id_tokens and access token hashes, as well as verify the token issuer 
and audience - or you could have a baseline level of security by using the code 
flow.

> Further, in the beginning paragraph of 7.8, you mention that implicit gets 
> the AT through the front-channel. Exchanging code for AT will also happen in 
> the browser , where instead of a url you will have an xhr (and again, now we 
> have cors)
> 
> Finally, how is the AT going to be refreshed? Are we allowing for long lived 
> RT in the browser? I see that the document mentions CSP in 7.7, but doesn't 
> the same apply to securing AT with Implicit?

Refresh tokens are used for two different purposes, and this might be worth 
clarifying for those setting their security policy:

1. refresh tokens for “offline” access, meaning that the client may perform 
actions on the user’s behalf while the user isn’t around. Typically, this means 
the refresh token lasts until the user or AS revokes it, so authorization thus 
also remains until revoked.
2. refresh tokens as a signaling method for re-authentication. In this case, 
the idea is that tokens are being used “online” as part of user interaction, 
with the application being forced to send the user to the AS to re-authenticate 
when the access token can no longer be refreshed. If the AS can track consent 
to the client (by a unique client identifier or via a mechanism like 
id_token_hint), this re-authentication may still require no user interaction.

For public clients, I see us using the second “online” refresh tokens. Whether 
they are long-lived or not really depends on the AS policy for 
re-authentication. If the client is being run on a device falling under 
corporate management, the AS might decide to make those particular refresh 
tokens last indefinitely.

-DW

_______________________________________________
OAuth mailing list
OAuth@ietf.org
https://www.ietf.org/mailman/listinfo/oauth

Reply via email to