So I'm trying to figure out if there's ANY way in which non-TLS-capable clients (i.e., clients that cannot receive TLS requests, e.g., because they're stuck in a shared-hosting environment and can't have dedicated IP, can't use SSL URIs, etc... even if they *can* initiate TLS connections to the auth server) can use the authorization code flow securely.
And it seems to me the CSRF scenario (10.12) makes this COMPLETELY hopeless unless the following are requirements are introduced (this would be a modification of 4.1.2/3): (*) When a "state" parameter is provided, the authorization code ultimately issued needs to be bound to that value as well (i.e., in addition to being bound to the client identifier and the redirection URI). (*) The access token request (4.1.3) needs to be allowed to include a "state" parameter and, if included, the authorization server MUST then reject the request if the provided state value is not identical to the corresponding value from the original authorization request. (*) A client MUST NOT use a particular state value for more than one authorization request. If a given (client_id, state) pair is used more than once, the authorization server MUST deny the authorization request, MUST deny any subsequent request for an access token for that client based on that state value, and SHOULD attempt to revoke all tokens previously issued for that client that are based on THE code derived from that state value. Oddly enough, this leads to some desirable properties. This, along with the existing requirement that authorization codes cannot be reused, in a sense, "guards both ends" of the redirection chain that - begins with the initial client response (to whatever request) that transmits the state value to the browser, and - ends with the final browser request that transmits the code to the client's redirect_uri, of which only the first and last messages can be non-TLS-protected (because all other requests/responses are between the browser and the authorization server, which is required to use TLS). The key point is that, with the above requirements, for any given (client_id, state) pair, at most one corresponding redirect chain can be carried to completion (i.e., issuance of an authorization code) While an attacker who discovers the state value can attempt to obtain a valid authorization code with her own credentials, if she does so and her authorization request reaches the auth server first, then the legitimate resource owner's own such request will fail in an obvious way, and, having seen this failure, said owner will then have reason to know that any subsequent report by the client that access has been granted is necessarily bogus. In this world, the authorization code, rather than being a bearer instrument that must be kept secret at all costs, now becomes merely a certificate that a redirect chain was carried to completion on SOME browser SOMEWHERE. The client, upon receiving the state value at the redirect_uri WILL be able to verify that the request came from the same browser that it originally sent the state value to (whether because the request is accompanied by a matching 'secure' cookie **OR** because the browser and client are, say, using digest authentication and state is bound to the hashed user:realm:password secret they share -- which does NOT entail TLS), An attacker may still be able to launch a CSRF request at redirect_uri AND have sufficient network control to block the legitimate request from getting through AND be able to use the same state value so that the client won't be able to detect the substitution. BUT, if she doesn't use the same authorization code as well, the authorization server will note the mismatch and client's subsequent access_token request will fail. And if she uses the same code, she's not deriving any benefit other than to be able to do DOS attacks. Thus, both the state value and the code can now safely (or at least more safely than before) be made public. Conversely, without these additional requirements, i.e., if the authorization server does NOT check that the code matches the state given in the access_token request, then the CSRF undetectably succeeds EVEN IF TLS is being used at redirect_uri. And if the state can be used more than once to obtain a valid code, then it can be used in other browser sessions and the CSRF attacker indeed will have something to substitute that can do damage. Therefore, with the current spec, if the state value can leak out AT ALL, it's game over. Which then means that a non-TLS-capable client, which has no secure way to transmit the state value to the browser, is COMPLETELY USELESS in OAuth2, At which point I don't understand why the current spec doesn't just require TLS clients and call it a day. -- Roger Crew 206.940.5732 c...@cs.stanford.edu _______________________________________________ OAuth mailing list OAuth@ietf.org https://www.ietf.org/mailman/listinfo/oauth