OAuth is not secure or I didn't understand it? - security

I was thinking about security for my REST web Service API, and decided to take a look at others large services and how they do it. As an example I decided to study Twitter's OAuth. After reading beginners guide I'm a little be confused and shocked.
As I understood it's Service provider responsibility to authenticate user and to show User what kind of access consumer is demanding (for example it want's read only access to specific resource). But I saw service providers that doesn't inform user on what type of access consumer is demanding (and even now showing consumer's identity). The second part of problem is that consumer can show his own custom Provider Service Authentication form in IFrame, and just hide access details, they can just steal you password, or request unlimited access to you resources, they can do basically what ever they want, there are lot's of way to trick user.
As an example let's take a LinkedIn. They request your gmail username and password inside their own form, and you have no idea how they will use it. They can just steal it and store in their DB, they can OAuth with it to gmail (and they don't show gmail's page with information what type of access they request), they can do whatever they want with this information.
What I'm trying to say is not that OAuth communication protocol is not secure, but rather there are lot's of way to use it improperly to trick the user and get his credentials.
BTW there were some security flaws in OAuth protocol itself: (http://oauth.net/advisories/2009-1/) and I'm pretty sure there are more, but no one cares to find them.

I'm going to go with 'You didn't understand it.' (In your defense, very few people do.)
Let's be clear: The session fixation attack you're referring to affected OAuth 1.0, but was resolved in OAuth 1.0a, which became RFC 5849. There are no major implementors of OAuth 1.0 — the major implementors all either implemented OAuth 1.0a/RFC 5849 or they implemented one of the OAuth 2.0 drafts.
As for the username/password anti-pattern, OAuth 1.0a does not provide for a mechanism to exchange a username and password for an access token. OAuth 2.0 does, but only for the purposes of supporting installed applications. Keep in mind that an installed application could simply keylog (or similar) if it really wanted to. When it comes to security, all bets are off if an application is already running natively and unsandboxed on the client's machine. But this is actually a very different scenario than what you're talking about. Web applications in both OAuth 1.0a and OAuth 2.0 don't ever touch the username and password.
The flow for OAuth 1.0a goes like this: The application asks the provider for a request token, telling it all of the things it wants access to. The provider issues the temporary unauthorized token, at which point the client may send the user to the provider to authorize that token. The user logins in with their username and password on the provider's site and then either grants or denies access. The provider then redirects back with a verifier string that allows the site to upgrade to an authorized access token. All of these interactions are signed. If the signatures don't match on any of them, the provider will reject the request. And the user can revoke any token at any time, removing the client's ability to access their account.
There are a number of security considerations with the protocol, but if you actually read the list, it's essentially the same list of the security issues that affect almost every site on the internet. These security considerations are all very well known and very well understood. To my knowledge, there are currently no known exploitable attacks against providers that correctly address all of these security considerations.
Point being, you are much safer using OAuth 1.0a or OAuth 2.0 to authorize a third party than with any of the alternatives. If you don't feel comfortable with these, the solution is simple: Don't authorize third parties to access your account. There certainly are plenty of reasons why you might not want to do that.

It sounds like you are confused about what's not secure. As I understand it, the OAuth protocol itself, if implemented properly, is secure. It's just that it's easy to implement improperly, and users get confused because they don't really understand what they are doing.
For example, what LinkedIn is doing is all wrong. I would never give them my gmail account information in this way. In order for me to provide my gmail account information, I insist on seeing that my browser is using SSL with Google and so the root frame of the page comes from Google.
Then there is the matter of trusting Google to correctly tell me what access is being requested and by who. If I don't trust them to do this, I shouldn't be using OAuth.

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.

For the sake of security, what's the benefit of the id token provided by OIDC? What if id token is stolen?

I have read a lot about OIDC and OAuth2, I know the id token is mainly used for the client to know who the user is and whether the user is still online currently.
Furthermore, Id token can prevent a class of impersonation attacks [You can find more details in this article].
But what if the id token is stolen? Can the attacker uses the id token to impersonate a user?
In our project, we just ensure https besides the OIDC. What else security consideration should I take to mitigate the impersonation attacks?
The goal or purpose of OIDC is not to be more secure than OAuth2, and this kind of comparison doesn't make sense. They solve different problems.
Let's start with OAuth2. In very short and somewhat simplified, OAuth2 solves the problem when a website holds data of a user, and that user wants to grant access to some of their data to another website. Say you have a Facebook account, but want to allow my application to access some of your data on Facebook, or for a more concrete example, you want to allow my awesomeapp.com app to post a link to your Facebook wall. For this, my website redirects you to Facebook, you log in, get an access token, and send that access token back to my website so that I can use it in your name to get what you allowed me to.
Note that there is one thing missing. I have no idea who you are. I just had an access token, with which I can do stuff, but I don't have identity info about you. Sure, this can be abused in different ways, the access token can hold your email address or whatever, but it's limited, the size matters, and there is no standard way.
At least not until OIDC comes in the picture. OIDC provides the identity element.
The purpose of the ID token is to provide identity info, to tell me claims about who you are. It may claim what your email address is, what security groups you are in, which company you work for, or anything else. Also it may be used to download more claims, in case they don't all fit in the actual token (see userinfo). These claims come from the Identity Provider, say Facebook, which my application then has to trust of course, i.e. I will believe whatever Facebook tells me about you.
This is all possible with pure OAuth2, but there is no standard, well known way to do so (or well, it is OIDC :) ). You could invent and implement something yourself, but these things are more complicated than they may first seem to be. That's why OIDC was invented, so you don't have to. But after all, OIDC is just a way to use OAuth2 to provide identity. In the end, it's just an extended OAuth2 if you like.
As for what security considerations you need to take into account - this part of your question is way too broad and can't be answered unfortunately. Security is a very complex topic.
I'm not really a security purist so my additions to Gabor's points are from a more practical viewpoint, as someone responsible for building well architected UIs and APIs:
An id token represents proof of authentication to a UI
An id token is NEVER used by APIs, which must use access tokens instead
An id token is the only type of token a UI should ever read, and it is mandated to have a JWT format
For Web UI logins an id token provides extra security, since it enables the UI to validate tokens and protect against some types of token substitution attack - so yes - OIDC is more secure
An id token is sometimes needed in order for logout to work
You should ALWAYS use a certified security library that does this type of work for you, rather than reading tokens directly in your own code.

OAuth authentication client side security issues

I understand the security issues around attempting to use OAuth for authentication from a provider's point of view. However I've been asked to provide users the facility to log on to a new web application using OAuth and obtain their basic identity info from the likes of Google and Twitter, from which a new user account within the client application will be created. Additionally users will be able to regster/login directly via user/passwords for anyone not wishing to use third party accounts.
We do not require any access to the user's details/info or providers APIs, just their basic identity when they first logon, and of course allow them to login via the provider in the future. Not exactly the use case OAuth is intended for, OpenId would have been preferred, but OAuth has been specified and without valid concerns would need to be adhered to.
My question is how safe is it to assume that the user has correctly authenticated themselves with the relevant provider. If I trust say Google to perform adequate authentication and I obtain an access token and their identity, presumably I can consider that a legitimate user? There are obviously issues if some one has access to the resource owners machine and saved passwords in the browser but that issue is present for those users who elect to register directly.
Presumably it possible to fake an access token, e.g. man in the middle pretending to be google? A MITM could fake an access token and supply identity details that matched a registered user's google id? I don't see anything for a client to know that the information definitely came from the provider. Obviously this problem is not unique to OAuth.
Are there another ways someone could illegitimately access an account that used OAuth to authenticate themselves.
OAuth allows that an application to access a specific user resource (that has been provided permission by the user) and it cannot go outside that scope. I have not seen the documentation that refers to creating a new user using OAuth based application.
That being said:
We do not require any access to the user's details/info or providers
APIs, just their basic identity when they first logon
This violates OAuth authorization process. The Service Provider does the authentication and provides the relevant tokens (based on the success of the authentication). This is to ensure that there are no 3rd party authentication done during the OAuth authentication process.
My question is how safe is it to assume that the user has correctly
authenticated themselves with the relevant provider.
This all depends on the service provider itself. To conform to OAuth protocol, one of the requirement is that user authentication must be done in a secured transport layer with a digital certificate (for HTTP, it must be done in HTTPS). OAuth consumer don't have any reference to the authentication process. Also the authentication process basically asks the user if the consumer can access the resource of the specific user (and not anyone else, since he doesn't have authorization to it).
Is it possible to fake an access token, e.g. man in the middle
pretending to be google?
Spoofing a Service Provider IS possible but it'll be tedious. For one, you will have to create a whole OAuth handshake process, create the exact API as the service provider, also setup an environment that is secured (as OAuth recommends). The only thing the spoofing service provider can obtain is the client credentials. If it has its user credentials, there is no need to use the application as there is no way of providing a user credentials using an application to do malicious damage.
Secondly, access tokens do expire so even if you spoof and retrieve an access token, the original application owner can ask for the service provider to block the application and the access token can be useless.
A man in the middle attack won't be possible. You will have to replicate the service provider in a sense that the end user won't be able to distinguish between the original and the spoofing service provider in order to capture all relevant credentials (from both the application and end user).
Sadly saying, the scenario from your last sentence is the truth.
But you should realise that the security is a huge and complex issue, especially in client side. It's not happen just in a single point but many points through the whole internet access life cycle. The scenario you given is not what OAuth try to solve.

Plain English explanation for usage of OAuth in conjunction to an internal user management

I'm new to OAuth, and although I have scanned through many documents, I don't seem to have yet a good architecture / design to a secure web application, answering most/all of OWASP Top Ten
My newbie questions are
Why can't I just rely purely on OAuth? why do a user needs credential in my own application?
If I do, do I need hash / salt anything if I save it? I don't store any passwords, but what about tokens?
I still need to persist the users so they won't login everytime, (like in OS) - do I
Somehow use the OAuth token (save it? does it make even sense)?
Or use the plain old httpOnly secure cookie (if so, what happens if they log out of the Oauth provider? shouldn't I in this case ignore my cookie and let them log out?
How do I implement logging out? I can't force them to log out of the OAuth provider, and if I only delete the httpOnly cookie / invalidate their session locally, is that enough? and security issues?
How do I implement single sign on? I don't want the user, after approving to click again "log in using Facebook / Twitter / Google" I want an effect similiar to SO (page refreshes and "welcomes you back" what are the best practices to do that? Why does SO refreshes the page (I assume it has to do with the fact it needs to be client side, but I don't fully understand how it works to even know what to ask)
I guess I have a lot to learn, but reading on so many potential security issues, and having to master so many different topics seems like a good potential for me missing something that someone later will exploit.
Is using a framework such as Spring Security, or using Lift's built in user management going to save me all this headache? or do I have to know exactly what I am doing to avoid things like Session Fixation, Cross Site Request Forgery, Cross site scripting, Rainbow tables and other things I only remotely get...
Why can't I just rely purely on OAuth?
From a service providers perspective, OAuth is a means of controlling access of third party applications to the business logic. The end user does not have to give out his password to the third party app, and the access can be controlled. For example, the provider could restrict the access to only parts of the service for limited amount of time.
If you write a third party application, there is no strict need for you to have your "own" user artifacts. You can rely on the users that authenticate your application.
You could require that user's have an account with a provider such as Facebook or Twitter and not implement any password stuff yourself.
(You probably need some sort of artifact to represent a user, it should in this case contain information about how that user authenticates your application, for instance an OAuth token, or an OpenID URL).
If I do, do I need hash / salt anything if I save it? I don't store
any passwords, but what about tokens?
Just to clarify, in OAuth a token is typically both a key and a secret, and they are needed in cleartext to sign requests (there are differences here depending on which version of OAuth you use). So you can store them encrypted, as long as it is reversible for you.
I still need to persist the users so they won't login everytime, (like in OS) - do I
somehow use the OAuth token (save it? does it make even sense)?
Yes this makes sense, a token represents your applications access to a specific user's data. Save the token if you want to keep a "session" alive.
How do I implement logging out? I can't force them to log out of the OAuth provider, and if I only delete the httpOnly cookie / invalidate their session locally, is that enough? and security issues?
There is no concept of "logging" out of OAUth, a token either has an expiration time or not. You can of course "log out" by simply choosing to forget the token. The next time you will have to redo the authentication. You cannot force users to invalidate an access token, unless the provider has an API for that.
You could save the token in a cookie, but I would use other unique identifiers for the session you want to keep alive. You can persist the details of the tokens server side. The information you store in your cookie shold make it possible to retrieve the token you need.
How do I implement single sign on? I don't want the user, after approving to click again "log in using Facebook / Twitter / Google" I want an effect similiar to SO (page refreshes and "welcomes you back" what are the best practices to do that? Why does SO refreshes the page (I assume it has to do with the fact it needs to be client side, but I don't fully understand how it works to even know what to ask)
If you save a token in a database, save an ID for that token in a nice secure cookie. When a user goes to your service, use the information in the cookie to make a call from your service, to the service provider, to check if the token is still valid. If so, you have established enough trust for you to "log in" the user in your application without having to go through the pain of the OAuth process again.
And as a side not, StackOverflow uses OpenID and not OAuth for user authentication. OAuth can be used for the same purpose but is mainly a specification for application authorization.
I hope this helped, and don't sell yourself short. This site is for posting questions, not for appearing all-knowing.

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