Which Authorization Grant to use for Django Oauth2 toolkit? - python-3.x

I am planning to deploy a separate resource server and an authorisation server, both running on django oauth toolkit. Assuming that the clients or the applications using our API services are in the same organization, and will host their frontend to use our APIs, and the users will be logged in on their side and we just have to authorize those clients (that are running the application).
Which Grant Type Should I use?

RFC 7636: Proof Key for Code Exchange
PKCE (RFC 7636) is an extension to the Authorization Code flow to prevent CSRF and authorization code injection attacks.
PKCE is not a replacement for a client secret, and PKCE is recommended even if a client is using a client secret.
Note: Because PKCE is not a replacement for client authentication, it does not allow treating a public client as a confidential client.
PKCE was originally designed to protect the authorization code flow in mobile apps, but its ability to prevent authorization code injection makes it useful for every type of OAuth client, even web apps that use a client secret.

Related

Emulating M2M auth if the server lacks client_credentials grant type

Xero Accounting API uses OAuth 2.0 but they seem to have intentionally omitted client_credentials grant type in order to sell what they call Custom Connections.
If we "don't want to pay for a Custom Connection, then you can still make use of Web or PKCE code flow for building machine to machine integrations but you'll need to request your tokens and handle authorisation outside off your application".
So I wonder if there's already a tried and tested way of managing the tokens especially in NodeJS or PHP in GCM or AWS cloud environments that I can use to establish a secure M2M communication after the initial OAuth user login.

Which OAuth2 authentication flow shoud I use for PWA + server side application

I am trying to choose the right authentication flow for an application:
Fontend is an Progressive Web App accessible only via HTTPS. It'is done in Angular, Single Page Application.
External Authorization Server
Backend accessible via REST calls
For now I am using Authorization Code Grant flow.
What have I tried:
I've checked official site. There is a list of possible flows (Authorization Code, Implicit, Password, Client Credentials, Device Code, ...),
but no clear indication how to choose between them.
Then I found this excellent article on Auth0.com. Unfortunately PWA + server side beckend is not present in their scheme.
Could you please tell me what OAuth2 flow is appropriate to my context and why?
Assumptions (the way I understood the question):
You own and develop both frontend (Angular app) and backend (server-side REST API).
You want to outsource authentication to a 3rd party identity provider.
You want the Angular app (Client) to hold the token and be able to authenticate on the backend (Resource Server), with the identity of your user (Resource Owner) established on the 3rd party (Authorisation Server / Identity Provider (IdP) ).
First, a sidetrack. For this use-case, OpenId Connect (OIDC) would be a better fit, because that supports the identity element. The point in OAuth2 is to authorize your app to do stuff on the 3rd party. What you want is establish the identity of your user, with the help of the 3rd party, and that's what OpenId Connect does.
Ok, so which flow (OIDC is still based on OAuth2).
The first questions are whether the Client is trusted to do anything on the Resource Server, and whether it can securely store a secret. This is clearly not the case, a client-side app is not trusted, and cannot hold a secret. In the client credentials flow, the client uses a secret to authenticate on the IdP to receive a token for the resource server. This would mean your Angular app stores a password which it uses to get a token for your backend, clearly not what you want.
Resource owner password credentials flow is used when the client is trusted to handle user credentials. In your use-case this is not good, because practically it would mean your Angular app would get the users password to forward it to the IdP in exchange for a token. Your Client should not have access to the user password, it is not trusted.
Now comes the more interesting part.
The question is whether your Client has a server-side to securely hold a secret. If it does, Authorization Code Grant is good, because it allows your user to authenticate on the IdP, get redirected back with an authorization code, and the server-side can then exchange that for an access token to be used on the resource server. However, your Client in this scenario does not have a server-side, as far as I can understand the API is the resource server. So this is not good for you, because it needs a client secret, and you can't store it in your Angular app.
And this pretty much leaves you with the Implicit Flow, for which you don't need a client secret, but on the other hand it's difficult to do things like refresh tokens. In the flowchart you linked to, the last question is whether your Client is an SPA - and in your case it is, so you should go for the implicit flow by default.
This is probably the most secure model for you, because even in case of a compromise of your Client, your user credentials are still safe (the Angular app never has access).
However, you can model this whole thing differently, and that simplifies it quite a bit.
As far as I could understand, you own both the Client and the Resource Server, and the Resource Owner is using the Client, you just want to offload authentication while you still manage users in a 3rd party service.
Looking at it this way, your Client is trusted to access user credentials, and the user using it is the Resource Owner. So you could use the Resource Owner Password Flow, where the user enters his credentials directly into the Angular app, which goes to the IdP, gets a token, and Angular simply uses that to access stuff on the API (Resource Server).
The risk compared to the Implicit Flow is that if the Angular app is compromised, user credentials will be disclosed to the attacker. Whether you want to accept this risk entirely depends on you. Note that this would obviously not work if the IdP is a well-known service (like a social website for example), because as your user I wouldn't want to give my social site password to your app. But as long as you manage users anyway, it can be acceptable to trust the Client.
While the previous anwser was perfectly accepted in 2018, it should be considerate as a security risk nowaday.
IETF source concerning implicit flow.
The correct flow to used now for a PWA and in general any public, browser based client that can not rely on client_secret is the authorization code flow + PKCE

How to Secure Oauth 2.0 Client ID and Client Secret

When an Android oauth 2.0 client application has client ID and client Secret hard-coded in it. it is very easy to decompile the application and retrieve the credentials.
Then What is the use of providing these credentials to oauth server.
It is not recommended to hard-code client_id and client_secret into a native app i.e. to use what is called a "confidential client" in a mobile app scenario exactly because the client_secret cannot be kept a secret.
A native app would typically be a "public client" to the Authorization Server i.e. one that does not have a client_secret. Security would come from the fact that a unique redirect URI is registered and additional OAuth features like PKCE (https://www.rfc-editor.org/rfc/rfc7636) are applied.
For general recommendations on using OAuth 2.0 for native apps see: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-native-apps, especially the security considerations at: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-native-apps-10#section-8

OAuth 2.0 Authorization Code Grant without secret

So I've been looking at setting up OAuth 2.0 for a Cordova mobile app using Microsofts cordova-plugin-ms-adal plugin (which uses the native libs) against a custom API using Azure AD. This all works well but I'm a bit confused with the use of the secret (or more specifically its absence).
In many articles on the web they state that when using the Authorization Code Grant and requesting a token, you include the secret. And that this grant type is ideal for use when you can securely store the secret e.g. on a server.
However the plugin does not require that a secret is specified in the app (and rightly so) but it still uses the Authorization Code Grant to authenticate. Also I can manually call
https://login.windows.net/common/oauth2/authorize?resource=http://***.onmicrosoft.com/***API&client_id=***&response_type=code&redirect_uri=http://***.onmicrosoft.com/***App
in my browser, login, get the code and then POST to https://login.windows.net/common/oauth2/token with
grant_type: authorization_code
client_id: ***
code: ***
redirect_uri: http://***.onmicrosoft.com/***App
resource: http://***.onmicrosoft.com/***API
and it works, so I get back a valid JWT, without having to send a secret.
Why!? Is this less secure? (I also noticed that the OAuth 2.0 spec section 4.1.3 does not state that the secret is required for grant type Authorization Code!?)
What are the implications of using a grant type of authorization_code without a secret / basic auth header?
Using the Authorization Code grant with a so-called confidential client (a client that has a client secret) is more secure than using a public Client indeed.
That is because the exchange of the authorization code itself happens as URL parameter in the front-channel i.e. through the browser and as such is relatively vulnerable to attacks like cross-scripting, click-jacking, network/DNS manipulation etc. That means that it is possible for a dedicated attacker to steal the authorization code from a user in certain circumstances (sloppy user, attacker network control, sloppy redirect URI matching in the server implementation, etc.).
To exchange the authorization code for an Access Token, a confidential Client would have to present the client secret on an HTTPs protected call alongside of the authorization code, whereas a public Client doesn't have any means of making sure that it is really the designated Client.
This means that it is relatively easy for an attacker to mimic a public Client since that requires only non-secret information (he can grab the client_id and the redirect_uri from his own browser) and the authorization code that he can grab through an attack as described above.
Though grabbing the authorization code for a confidential Client works in the same way, the attacker cannot use it and exchange it for an Access Token because in order to do so he needs a client secret which is typically much harder to obtain for the attacker. The secret is usually stored on the server in backend storage and communicated only over a secure HTTPs channel so it doesn't leak.
The implication of using grant_type=authorization_code (or any other flow) with a public client (one that does not have a secret or authenticate in any other way) is that the access token granted does not represent an authorization of the client to directly access the resource, it represents an authorization for the client to access the resource on behalf of the user.
This is why you'll notice in Azure AD that when you register a native client app (a public client) you can only configure it to have delegated permissions to a resource, and not app-only permissions.
without having to send a secret.
Not true. In the link you posted the request includes also:
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Maybe you didn't notice it. This shows the client_secret being transmitted in an encoded form, using HTTP Basic Authentication.
It's up to the server to decide how the client authenticates (if necessary). From the specification :
If the client type is confidential or the client was issued client
credentials (or assigned other authentication requirements), the
client MUST authenticate with the authorization server as described
in Section 3.2.1.
Sec 3.2.1 directs to section 2.3 (seriously), which says:
Clients in possession of a client password MAY use the HTTP Basic
authentication scheme as defined in [RFC2617] to authenticate with
the authorization server.
client password is aka client secret.
So the secret is being transmitted.

Does an OAuth 2 client really need TLS?

I intend to build a delegated login system for an existing app. I'll be implementing both the OAuth client (in a web application) and the OAuth server (a simple authorization and resource server, that really only has a 'user' resource for now.)
With that in mind, I came across the following section in the current OAuth 2 draft (version 22):
3.1.2.1. Endpoint Request Confidentiality
If a redirection request will result in the transmission of an
authorization code or access token over an open network (between the
resource owner's user-agent and the client), the client SHOULD
require the use of a transport-layer security mechanism.
Lack of transport-layer security can have a severe impact on the
security of the client and the protected resources it is authorized
to access. The use of transport-layer security is particularly
critical when the authorization process is used as a form of
delegated end-user authentication by the client (e.g. third-party
sign-in service).
This specifically warns me that I should be using TLS on the client. We will be using HTTPS on the server, of course, but enabling HTTPS on all clients will be difficult if not impossible.
From my limited understanding of security, I imagine someone could steal the authorization grant. This brings me to my question:
Won't client authentication (using the client secret) prevent an eavesdropper from using the authorization grant? (Because the malicious party won't know the client secret, hopefully.)
If it doesn't, or if there's another attack vector here I'm not seeing, is there anything I can do to make this work securely without HTTPS on the clients? Would, for example, OAuth 1 help? (Perhaps because it has the additional request token step.)
P.S.: I was planning on doing client authentication using TLS client certificates, rather than secrets, if that makes the situation any better.
I think you are misinterpreting part of this warning. This OAuth warning is addressing OWASP A9 violations. This is saying that even though you are using OAuth you still need a secure transport layer to communicate with the client. The client doesn't require a key pair for authentication, OAuth is the client's form of authentication. However, the browser still authenticates with your application using a session id stored as a cookie value. The concern is that if an attacker is able to intercept this value, then he will have the same access as the victimized client.

Resources