How to Secure Oauth 2.0 Client ID and Client Secret - security

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

Related

Which Authorization Grant to use for Django Oauth2 toolkit?

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.

Autentication Azure ad Client Secret is necessary?

I have the following doubt, I have a project that is based on microsoft authentication, a frontend with angular using msal and the backend with passport-azure-ad.
My question is the following, is it necessary to use the client secret?
When we are using authorization code flow or hybrid flow in OpenID Connect, the client exchanges an authorization code for an access token. During this step, the client has to authenticate itself to the server. One way to authenticate the client is by using a client secret.
Client secret is required for web apps which can store the client_secret securely on the server side.All confidential clients have a choice of using client secrets or certificate credentials and passport azure ad library is designed for auth flows in server side web apps.
Note:ClientID and Client Secrets are passed to AAD by MSAL, and if you are using a confidential client (like: WebApp, WebAPI or
Daemon/Service) that runs on Azure PaaS Service, or any other secured
servers, only the clientID gets exposed by MSAL but not the client
secret, as the client secret is passed only in the backend (server
side) to AAD and never directly exposed and requires proper
authentication.
msal client apps
If your app is native(spa), client secret is not needed
Public clients, which include native applications and single page apps, must not use secrets or certificates when redeeming an authorization code as client_secret can't be reliably stored on devices or web pages and the secret can be vulnerable to attacks if it is client side exposed..
Reference: v2-oauth2-auth-code-flow-Client secret

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

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.

OAuth - embedding client secret in your application?

I'm looking at the oauth implementation twitter proposes here:
https://dev.twitter.com/docs/auth/oauth
and oauth libraries like signpost:
http://code.google.com/p/oauth-signpost/
they both talk about using the client secret during the oauth flow, which means for my client application, I'd need to store the secret in the application itself. This is probably risky as someone could grab the secret out of my app. Are there any methods around storing the secret within my app? Am I misunderstanding the oauth flow?
Thanks
There are no ways of storing client credentials in a native or JavaScript application without making them practically public. Also, putting those credentials on a proxy server and having the client talk to the server (so that the credentials are not exposed) doesn't really solve anything either. Now you have a problem of authenticating the client to the proxy.
The right solution is to have special support for native applications provided by the OAuth service. OAuth 2.0 uses pre-registered redirection URIs and other techniques to accomplish a reasonable client identity verification for such clients.

Resources