OAuth 2.0 public client impersonation - security

I'd like to develop a native application (for a mobile phone) that uses OAuth 2.0 Authorization to access protected resources from a resource API. As defined in section 2.1 the type of my client is public.
Upon registration, the Authorization Server provides a client_id for public identification and a redirect_uri.
The client will make use of Authorization Code to receive it's Authorization Grant from the Authorization Server. This all seems secure (if implemented correctly) against any attacker in the middle.
In section 10.2 client impersonation is discussed. In my case, the resource owner grants the client authorization by providing it's credentials via the user agent to the Authorization Server. This section discusses that the Authorization Server:
SHOULD utilize other means to protect resource owners from such
potentially malicious clients. For example, the authorization server
can engage the resource owner to assist in identifying the client and
its origin.
My main concern is that it's easy to impersonate my client once the client_id and redirect_uri is retrieved.
Due to the nature of a public client, this can either be easily reverse engineered. Or in my case, the project will be open source, so this information can be retrieved from the web.
As far as I've understood from section 10.2, it's the resource owner's responsibility to check that the client is legitimate by comparing with what the Authorization Server SHOULD assist with.
In my experience with third party applications requesting an Authorization Grant from me, all I get is a page with some information about the client that actually should be requesting that grant. Based on pure logical sense, I can only judge if the client that's requesting the grant is actually the client that the Authorization Server is telling me who it should be.
So whenever we are dealing with PEBKAC (which I think occurs frequently), isn't it true that impersonators can easily access protected resources if the resource owner just grants them (which might identically look like my legitimate client) authorization?

TLDR - You want oauth access tokens to be issued only to valid clients - in this case devices that installed your app, yes?
First - Oauth2 has multiple workflows for issuing tokens. When YOU are running the Oauth2 service and its issuing tokens to devices running YOUR app, authorization code / redirect URL is not the relevant workflow. I suggest you read my answer here - https://stackoverflow.com/a/17670574/116524 .
Second - No luck here. Just run your services entirely on HTTPS. There is no real way to know whether the client registration request is coming from an app installed from the official app store. You can store bake some secret into the app, but it can be found via reverse engineering. The only possible way this could possibly happen can be some sort of authentication information being provided by the app store itself, which does not exist yet.

Related

Is Oauth2.0 appropriate for first-party apps?

I am developing a SPA application in angular and I have a lot of confusion about the correct way to implement authentication and authorization.
First of all, the application is a first-party app, which means that I am developing both the authorization server and resource servers.
The users that logs in the application must have full access to their resources on the platform.
So, I am doing it using OAuth2.0 and I have a couple of doubts about the domain of the protocol as well as security concerns.
First question:
The first question is if OAuth should be actually used to authorize first party applications. From my understanding this is a delegation protocol used to grant a third-party application controlled access to the user's resources on the platform, upon user consent. How does this fit in the context of a first-party app? In that case the app should get an access token with a scope that allows full access, right?
Second question:
Since this is a Single Page Application I couldn't store a secret on client side. So I am opting for using the authorization code grant with PKCE which would seem to be appropriate to manage this scenario. In this case I wouldn't ask for a refresh token but I would only retrieve the access token and using silent check to refresh it. I do not want to have refresh token insecurely stored on the browser. Is this PKCE really secure? The secret is generated dynamically but a attacker could eventually create a system using the same public client id and managing the PKCE properly, and finally get an access token that, in my case, gives full access to the users resources.
I could in the future allow controlled access to my app's resources to third party app, that's also one of the reason why I stick with OAuth.
The first question is if OAuth should be actually used to authorize first party applications. From my understanding this is a delegation protocol used to grant a third-party application controlled access to the user's resources on the platform, upon user consent. How does this fit in the context of a first-party app? In that case the app should get an access token with a scope that allows full access, right?
Yes, this makes sense to me. We skip the 'grant permissions' step for our own apps.
Is this PKCE really secure?
Yes, even without PKCE, authorization_code is pretty secure. Adding PKCE solves a a few potential security issues, but I would be somewhat inclined to call them edge cases. It is definitely right now the recommended choice.
The PKCE rfc has more information about the motivations behind PKCE:
https://www.rfc-editor.org/rfc/rfc7636#section-1
I actually came here looking for the answer to Question 1. My take is that in situations where we have no third party apps requiring access to our APIs we do not need OAuth. If we still need to use OAuth, then we can use Resource Owner Password Flow for first party apps. I have not seen any convincing answer anywhere confirming or rejecting this opinion but this is purely based on my understanding of OAuth.
Now, I am mainly writing this to answer Question 2. PKCE protocol is secure and attacker would not get token in this scenario. The reason is that the Authorization Server uses pre-registered "Redirect Uri" to send the token to. To be precise, the Auth Server would simply ask the browser to redirect user to "Redirect Uri appended with Access Token". Browsers do not allow javascript interception of Redirection requests. Therefore, an attacker would not be able to get hold of the token and the user will be redirected from attacker's site to yours at the end.

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

What is preventing fake apps from hijacking a legitimate apps OAuth2 clientId?

What is preventing the following scenario:
Attacker downloads legitimate app that makes a legitimate OAuth 2.0 Authorization Grant to a desired resource
Attacker records the client_id and redirect_uri
Attacker creates phony app in the image of the real thing
Victim downloads phony app and begins OAuth 2 flow for desired resource
Phony app provides identical client_id and redirect_uri as legitimate app
Victim authenticates and authorizes use of desired resource
Phony app catches the redirect without ever hitting URL (I know iOS can do this) and securing its contained authorization code.
Phony app now has access to desired resource "in the name" of a legitimate app
Is there any way to actually validate the identity of an app making an authorization request when using a public client (no client_secret)?
There is no inclusive protection against that threat as the OAuth 2.0 security considerations spec acknowledges: https://www.rfc-editor.org/rfc/rfc6819#section-5.5. It acknowledges that the user plays an important role here. Some remarks though:
App installation control via Mobile Device Management may be applicable in some (enterprise) use cases to mitigate this.
Dynamic Client registration (http://openid.net/specs/openid-connect-registration-1_0.html) may be used to generate a per-instance client secret so that after registration the Client is a confidential Client. Yet the the app integrity question then still exists (only) in the initial bootstrapping/registration phase.

Oauth Implicit Grant web api authorization server

I am looking at the following example for the implicit grant.
http://code.msdn.microsoft.com/OWIN-OAuth-20-Authorization-ba2b8783
I can see how the example is redirecting unauthenticated user to the same authorization serer's log in page. which is something like follows:
Client ---> AuthServer ---> 401
|
<--- Login (UI) <------
(On Auth server)
My problem is that I dont want to authorization server to handle UI part of login page. That is my authorization server is a web api and its only job is to process the owin pipeline and authenticate user via webapi.
So ideally what I would like to do is, that authorization server respond with 401 to the client. Client (could pure js app) show login page (username/password) and POST to authorization server with username/password over SSL and auth. server says you are ok to login.
This will give all the client to manage Look and feel of their login page but the authentication (logic) part is done via auth server webapi.
Is this possible?
Are there any security implication that I need to be aware of when implementing this (only specific to this scenario) ?
Thanks
If the implementation of the authorization server supports "Resource Owner Password Credentials Grant" and allows your application to use it, you can implement your scenario. However, it is unlikely that the authorization server does.
The primary purpose of OAuth 2.0 is to allow third-party applications (like your application) to access protected resources of end users (= resource owners) without passing end users' credentials (username/password) to the third-party applications. So, your scenario is the very use case that OAuth 2.0 tries to avoid.
[Comment to your additional question]
If you are an implementor of an authorization server, yes, you can implement both "Implicit Grant" and "Resource Owner Password Credentials Grant". It's up to you. On the other hand, if you are an implementor of a client application which accesses an authorization server that has been implemented by someone else (at least not by you), whether your client application can use "Resource Owner Password Credentials Grant" depends on the implementation of the authorization server. What I meant was that in general authorization server implementations would not give a chance for third-party applications to use "Resource Owner Password Credentials Grant", because it's a kind of the last resort and the specification (RFC 6749) says "The authorization server should take special care when enabling this grant type and only allow it when other flows are not viable."

OAuth 2.0 Implicit Grant Flow - clientId and accessToken exposure security

Since OAuth 2.0 Implicit Grant Flow exposes its mechanism e.g. using JavaScript, in the client app to the resource owner, the client Id and the access token are exposed. I have not been able to find a clear answer on what can be done to prevent from exploiting the exposure.
What are some measures to prevent problems with the following scenario? If it's apparent that I am not understanding the flow correctly, please do point out.
Scenario
Client A - a legit client who has been granted its own unique client Id from the authorization server.
Client B - a client the authorization server is not aware of, copies the client Id of Client A, draws in innocent resource owners and uses their access tokens to gain access to their private information.
These are some options I can think of to fix the issue.
Create an IP white list and map to each known client. Check against the authorization server when authorizing and calling the resource server.
Set throttling on the end points of the resource server to detect abnormal activities.
Well, this is the reason why the OAuth specification (RFC 6749) warns against about security weaknesses of the implicit flow in Section 10.6. It's not clear that the counter-measures you describe would be effective in a general setting on the internet. For example, IP headers are insecure and can be easily spoofed. I would only use the implicit flow for the applications that require the lowest level of security (e.g., read-only display of information).
The token is secured using SSL between the client and the server. Therefore the content is encrypted but the URI is not. You can put store the token in the html body because it is secure with the exception of browser add ons. Don't use third party content servers to host JavaScripts, if they are compromised their scripts can read your html. The user can see the token and copy it to their own app if they want but its protecting their resources so... Ultimately I like Implicit flow because of its simplicity.
Ultimately the servers handling of the token can be a problem out of your control. Chose a server that does not include the token in the URI, its not safe. Similarly your shouldn't post back to the server sensitive information in the URL.
If you find a library that guarantees security, please post it.

Resources