Native app OAuth2 authorization - security

we want to create a native mobile app using OAuth2.
How to protect from stealing clientID (this information can be obtained by anybody)? Someone can create his own app and act as our app by using our clientID?

Yes, if someone retrieves your clientId/clientSecret, he can act as your app and sadly, there is no way to fully remove credentials from your application.
At a higher level, your app needs an identifier and a secret to authenticate to your service. If you remove the secret from your app, you need to get it from somewhere else (it could be your user typing it, this would be the same as having an auth for the user and giving him a token to perform further API calls).
However, you can make it harder for reversers to obtain the credentials, as explained in this article.
To make it even harder, you could force all your API calls to be done in HTTPS and enable SSL Certificate Pinning thus making Proxy Debugging/Man In The Middle difficult to pull off.
Ultimately, you should clearly identify which API calls should be public (with only the OAuth token to access those resources) and which should require a user authentication.
PS: Google's (Android Security Best Practices)[https://developer.android.com/training/best-security.html] could be a good start !

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.

Are OAuth Access Tokens confidential?

I have a web application which uses OAuth 2.0 to talk to a third-party service. I want both my server and my web app to talk to the authorized service on behalf of the user. I go through the normal authorization steps of doing the redirect, getting the auth code, exchanging it for the access token, all that jazz. Once complete, my server has the access token and can talk to the service. However, I'd like the web app to talk to the service as well so I don't have to route everything through my server.
Can I send the access token to the web app so I can achieve this? Or, is the access token supposed to be kept confidential between my service and the service, never being disclosed to the user, just just like the client secret is?
I've tried to find an answer for this in the spec and various blog posts, but haven't found a definitive answer either way. I know there is an implied auth method for client-side apps which don't involve a server-side component at all. Therefor my initial guess is that I can send the token to the client. I would like to verify this though.
The token is considered very sensitive information because it allows access to the service. Anyone could issue requests if they had this token.
This is why the token is passed in the Authorization Header, this is why it's highly recommended you make all calls over https, to protect the headers and body information. This is also why it is recommended that the tokens have s short life span so that if one is indeed compromised, it doesn't last for long.
Yes, you can share this token between your own applications and it should work, provided the receiver of the token does not store the IP addresses of the callers as well or has some other check mechanisms in place.
The ideal situation however would be for you to issue a different set of ClientID and Client Secret to each application which requires access.
Don't forget that this is the way the applications identify themselves to the receiver side and it might be important for reporting and analysis purposes.

Login App with IdentityServer4

I have to develop a SSO system and I have to do it using IdentityServer4. I have gone through the documentation and examples but I have some doubts. To be honest I don't quite get it, but I am really new in Oauth2 and OpenId Connect.
We will have a bunch of clients (web apps), each of one of those will have their own Web APi. And we have to have a centraliced Login App for all of those. I think the example with the javascript client is the closes to the thing we want to achieve. Also, a user might have permission to access one client (app), but not another, so the IdentityServer must provide information about wich clients (apps), that particularly user can access.
So, These are the things I don Understand:
1.- In the documentation I can read there are two tokens, an Identity Token and Access token. But in the examples all I see are the access tokens. It seems to me that the access token is the one with all de info needed. am I wrong?
2.- Also, I have read about de Grant Types and I'am not quite sure wich one we must use. At first I thought to use the ResourceOwner password, because it requires the client, the secret, a user and a password, wich I assumed it could be the end user. I found this example http://sunilrav.com/post/How-to-Customize-Authentication-in-Identity-Server-4 were one could customise the class that validate the user and password. I thought that this could be the way to go but the documentation statesa about this grant type "...This is so called “non-interactive” authentication and is generally not recommended.". The javascript client example uses the implicit Grat type, wich the documentation states is for browser-based applications (our client apps will all be browser based using react).
3.- can my Login app be a Javascript (react) app? The example Quickstart is made in MVC.NET. This login app connects directly to de IS4 server without asking for a access token? (In the example the app is embebed in the IS4).
4.- Can I protect with IS4 a WEB API which is developed in .net framework (4.6.2) and not in .Net Core? I havent Found Any examples.
the documentatios I followed is the offcial. The examples (quickstart) are also there. (I can't post more than two links).
thank you very much for reading and for your help.
Identity Token and Access token
Identity token is the one that contains the identity of the user, that will tell the client app that what user it is. After successful login, user will be redirected to the client app with these tokens. Response will also have claims, such as permission scopes, name , email you can add custom claims as well.
Access token is used to access your protected web api resource. You have to send the access token with each request to access the api.
Grant Types
Grant types is basically how you want your client app to interact with the auth server. https://identityserver4.readthedocs.io/en/release/topics/grant_types.html
can my Login app be a Javascript (react) app? Your client app can be a javascript app but your auth server that is the identity server which will have the login/signup pages(and other login jazz) and account controllers should be you MVC app. As, everything is already done using MVC and Entity framework, why you want to re do everything.
Can I protect with IS4 a WEB API I am not sure about this one, but I dont see why you would not be able to do it.
This is a good answer for basic IdSrv flow!
UPDATE In my understanding, the answer to which Grant Type to use it depends on your client application requirement. If you want to use a Javascript client you can use Implicit Flow, but you won't be able to use refresh tokens and your access token is not 100% secured with the browser as client can access it.
If you want to open your web api to public then you can use client credentials flow. If you want to be more secure you should use Hybrid flow or HybridClient credential flow. ( again depends on the requirements ). with this you will be able to use refresh tokens and in this way your access token would be more secure.

client secret in OAuth 2.0

To use google drive api, I have to play with the authentication using OAuth2.0. And I got a few question about this.
Client id and client secret are used to identify what my app is. But they must be hardcoded if it is a client application. So, everyone can decompile my app and extract them from source code. Does it mean that a bad app can pretend to be a good app by using the good app's client id and secret? So user would be showing a screen that asking for granting permission to a good app even though it is actually asked by a bad app? If yes, what should I do? Or actually I should not worry about this?
In mobile application, we can embedded a webview to our app. And it is easy to extract the password field in the webview because the app that asking for permission is actually a "browser". So, OAuth in mobile application does not have the benefit that client application has not access to the user credential of service provider?
I had the same question as the question 1 here, and did some research myself recently, and my conclusion is that it is ok to not keep "client secret" a secret.
The type of clients that do not keep confidentiality of client secret is called "public client" in the OAuth2 spec.
The possibility of someone malicious being able to get authorization code, and then access token, is prevented by the following facts.
1. Client need to get authorization code directly from the user, not from the service
Even if user indicates the service that he/she trusts the client, the client cannot get authorization code from the service just by showing client id and client secret.
Instead, the client has to get the authorization code directly from the user. (This is usually done by URL redirection, which I will talk about later.)
So, for the malicious client, it is not enough to know client id/secret trusted by the user. It has to somehow involve or spoof user to give it the authorization code,
which should be harder than just knowing client id/secret.
2. Redirect URL is registered with client id/secret
Let’s assume that the malicious client somehow managed to involve the user and make her/him click "Authorize this app" button on the service page.
This will trigger the URL redirect response from the service to user’s browser with the authorization code with it.
Then the authorization code will be sent from user’s browser to the redirect URL, and the client is supposed to be listening at the redirect URL to receive the authorization code.
(The redirect URL can be localhost too, and I figured that this is a typical way that a “public client” receives authorization code.)
Since this redirect URL is registered at the service with the client id/secret, the malicious client does not have a way to control where the authorization code is given to.
This means the malicious client with your client id/secret has another obstacle to obtain the user’s authorization code.
I started writing a comment to your question but then found out there is too much to say so here are my views on the subject in the answer.
Yes there is a real possibility for this and there were some exploits based on this. Suggestion is not to keep the app secret in your app, there is even part in the spec that distributed apps should not use this token. Now you might ask, but XYZ requires it in order to work. In that case they are not implementing the spec properly and you should A not use that service (not likely) or B try to secure token using some obfuscating methods to make it harder to find or use your server as a proxy.
For example there were some bugs in Facebook library for Android where it was leaking tokens to Logs, you can find out more about it here
http://attack-secure.com/all-your-facebook-access-tokens-are-belong-to-us
and here https://www.youtube.com/watch?v=twyL7Uxe6sk.
All in all be extra cautious of your usage of third party libraries (common sense actually but if token hijacking is your big concern add another extra to cautious).
I have been ranting about the point 2 for quite some time. I have even done some workarounds in my apps in order to modify the consent pages (for example changing zoom and design to fit the app) but there was nothing stopping me from reading values from fields inside the web view with username and password. Therefore I totally agree with your second point and find it a big "bug" in OAuth spec. Point being "App doesn't get access to users credentials" in the spec is just a dream and gives users false sense of security… Also I guess people are usually suspicions when app asks them for their Facebook, Twitter, Dropbox or other credentials. I doubt many ordinary people read OAuth spec and say "Now I am safe" but instead use common sense and generally not use apps they don't trust.
Answering to 2nd question: Google APIs for security reason mandate that authentication/sign-in cannot be done within App itself (like webviews are not allowed) and needs to be done outside app using Browser for better security which is further explained below:
https://developers.googleblog.com/2016/08/modernizing-oauth-interactions-in-native-apps.html

How to keep the client credentials confidential, while using OAuth2's Resource Owner Password Credentials grant type

We are building a rest service and we want to use OAauth 2 for authorization. The current draft (v2-16 from May 19th) describes four grant types. They are mechanisms or flows for obtaining authorization (an access token).
Authorization Code
Implicit Grant
Resource Owner Credentials
Client Credentials
It seems we need to support all four of them, since they serve different purposes. The first two (and possibly the last one) can be used from third-party apps that need access to the API. The authorization code is the standard way to authorize a web application that is lucky enough to reside on a secure server, while the implicit grant flow would be the choice for a client application that can’t quite keep its credentials confidential (e.g. mobile/desktop application, JavaScript client, etc.).
We want to use the third mechanism ourselves to provide a better user experience on mobile devices – instead of taking the user to a login dialog in a web browser and so on, the user will simply enter his or her username and password directly in the application and login.
We also want to use the Client Credentials grant type to obtain an access token that can be used to view public data, not associated with any user. In this case this is not so much authorization, but rather something similar to an API key that we use to give access only to applications that have registered with us, giving us an option to revoke access if needed.
So my questions are:
Do you think I have understood the purpose of the different grant types correctly?
How can you keep your client credentials confidential? In both the third and fourth case, we need to have the client id and client secret somewhere on the client, which doesn't sound like a good idea.
Even if you use the implicit grant type and you don’t expose your client secret, what stops another application from impersonating your app using the same authorization mechanism and your client id?
To summarize, we want to be able to use the client credentials and resource owner credentials flow from a client application. Both of these flows require you to store the client secret somehow, but the client is a mobile or JavaScript application, so these could easily be stolen.
I'm facing similar issues, and am also relatively new to OAuth. I've implemented "Resource Owner Password Credentials" in our API for our official mobile app to use -- the web flows just seem like they'd be so horrible to use on a mobile platform, and once the user installs an app and trusts that it's our official app, they should feel comfortable typing username/password directly into the app.
The problem is, as you point out, there is no way for my API server to securely verify the client_id of the app. If I include a client_secret in the app code/package, then it's exposed to anyone who installs the app, so requiring a client_secret wouldn't make the process any more secure. So basically, any other app can impersonate my app by copying the client_id.
Just to direct answers at each of your points:
I keep re-reading different drafts of the spec to see if anything's changed, and am focused mostly on the Resource Owner Password Credentials section, but I think you're correct on these. Client Credentials(4) I think could also be used by an in-house or third-party service that might need access to more than just "public" information, like maybe you have analytics or something that need to get information across all users.
I don't think you can keep anything confidential on the client.
Nothing stops someone else from using your client id. This is my issue too. Once your code leaves the server and is either installed as an app or is running as Javascript in a browser, you can't assume anything is secret.
For our website, we had a similar issue to what you describe with the Client Credentials flow. What I ended up doing is moving the authentication to the server side. The user can authenticate using our web app, but the OAuth token to our API is stored on the server side, and associated with the user's web session. All API requests that the Javascript code makes are actually AJAX calls to the web server. So the browser isn't directly authenticated with the API, but instead has an authenticated web session.
It seems like your use-case for Client Credentials is different, in that you're talking about third-party apps, and are only serving public data through this method. I think your concerns are valid (anyone can steal and use anyone else's API key), but if you only require a free registration to get an API key, I don't see why anyone would really want to steal one.
You could monitor/analyze the usage of each API key to try to detect abuse, at which point you could invalidate one API key and give the legitimate user a new one. This might be the best option, but it's in no way secure.
You could also use a Refresh Token-like scheme for this if you wanted to lock it up a bit tighter, although I don't know how much you would really gain. If you expired the Javascript-exposed api tokens once a day and required the third-party to do some sort of server-side refresh using a (secret) refresh token, then stolen api tokens would never be good for more than a day. Might encourage potential token thieves to just register instead. But sort of a pain for everyone else, so not sure if this is worth it.

Resources