26

The specific use case I'm interested in here is authenticating REST clients against publicly-available server endpoints (such as a public REST API).

The simplest solution here is Basic Auth. But I often hear OAuth2 touted as a superior auth solution in almost all circumstances.

The thing is, the only OAuth2 grant type that is feasible for a REST client authenticating against a REST server is Resource Owner Password Credentials (ROPC), because Code Grants and Implicit Grants require a UI/webpage (hosted by the Auth Server) for the user to login to and manually authorize the client app.

The way ROPC works is, by sending the resource owner's username/password, and the client ID as query string params?!? This is even less secure (IMHO) then Basic Auth, which at least base-64 encodes the credentials and sends them inside a header which can be encrypted by TLS!

So I ask: in the context of public REST APIs, is OAuth2 ROPC really any better than Basic Auth? What is more secure than OAuth2 ROPC?


Update

I just read this excellent article which explains Amazon's non-OAuth2 based REST security for AWS. It is essentially a private key-based solution where hashes of each REST request are generated and sent as sidecars along-side the normal (un-encrypted) request. Only the client and the server know the private key, so when the server receives the request (again, containing the normal request + the hashed request), the server looks up the client's private key, applies the same hash to the normal request, and then compares the two hashes.

This sounds way more complicated, complex and secure than OAuth2's ROPC! Unless I'm missing something major here, OAuth2 ROPC is just sending client_id, username and password as query string params...totally and utterly unsecure! This HMAC/hashed-based solution seems to be much more impressive and secure.

The thing is, even the author of that article goes on to say:

You [will] also slowly realize and accept that at some point you will have to implement OAuth...

Ba-ba-bwhat?!?! If OAuth2 is less secure than this clever HMAC/hash-based solution, why does the author of this article feel OAuth needs to be embraced at some point. I'm so confused.

11
  • What kind of client are you talking about? I assume that most of the clients will have a UI. In which case, you can load up the OAuth login page in a webview (desktop, mobile) or redirect to it directly (web). I don't see why you need to avoid UI.
    – decyclone
    Sep 18, 2015 at 5:07
  • @decyclone please read the very first sentence to the question! I'm taking about REST (headless HTTP) clients authenticating against REST services.
    – smeeb
    Sep 18, 2015 at 10:09
  • The question I am asking is if that client has any UI at all? Even if it had not, I have seen applications with no UI pop a dialog at least for authentication.
    – decyclone
    Sep 18, 2015 at 13:00
  • @decyclone no a pure REST client has no UI whatsoever, although UI's typically use a pure REST client for connecting to a REST service. One use case is a command line tool that uses a REST client for sending user commands (entered on the shell) to the REST service. Popping a UI from a shell just isn't an acceptable solution here.
    – smeeb
    Sep 18, 2015 at 13:04
  • 1
    But, I should note, there are plenty of other use cases outside a command line/shell. Another use case is a Java/Ruby/Python pure REST/HTTP client that has no UI and might be running on a backend server that has no UI. The backend server needs to communicate with another backend server over REST. Here, not only would it be awkward and hacky to pop a UI when backend server #1 needs to speak to backend server #2, the real problem there is there's no browser/UI client to display the login page to, and there's no human being there to log in!!!
    – smeeb
    Sep 18, 2015 at 13:08

5 Answers 5

31
+75

The answer to your question can be at the code level, protocol level or architecture level. I will attempt to summarize here most of the protocol level issues since that is usually critical in pros and cons analysis. Keep in mind that OAuth2 is much more than Resource Owner Password Credentials which, according to the specification, exists for "legacy or migration reasons", is considered "higher risk than other grant types" and the specification explicitly states that the clients and authorization servers "SHOULD minimize use of this grant type and utilize other grant types whenever possible".

There are still many advantages of using ROPC over basic authentication but before we get into that, let's understand the basic protocol difference between OAuth2 and basic authentication. Please bear with me as I explain these and will come to ROPC later.

User authentication flows

There are four roles defined in OAuth2 specification. With examples, they are:

  1. Resource owner: The user who has access to some resource, e.g. in your case, different users may have different access level to the REST API;
  2. The client: usually the application the user is using, and needs access to the resource to provide services to the user;
  3. Resource server: the REST API in your case; and
  4. Authorization server: the server to which user's credentials are presented and which will authenticate the user.

When a client application runs, it is granted access to the resources based on the user. If a user has administrator privileges, the resources and operations available to the user in REST API may be far more than a user without administrator privileges.

OAuth2 also allows the possibility of using a single authorization server with multiple clients and for multiple resources. As an example, a resource server can accept user's authentication with Facebook (which can act as authorization server in such a case). So when the user runs an application (i.e. the client), it sends the user to Facebook. User types their credentials in Facebook, and the client gets back a "token" which it can present to the resource server. Resource server looks at the token and accepts it after verifying that Facebook in fact issued it and allow the user access to the resource. In this case, the client never sees user's credentials (i.e. their Facebook credentials).

But let's say you are managing your user's identities (and have an authorization server) instead of Facebook, which grants tokens to your client already. Now, let's say you also have a partner and you want to allow their application (i.e. client) to access your REST API. With basic authentication (or even ROPC), the user will provide credentials to that client which will send it to the authorization server. Authorization server will then provide a token that can be used by the client to access the resources. Unfortunately, this means that user's credentials are now visible to that client too. However, you would not want a partner's application (who could be external to your organization) to even know a user's password. That's a security issue now. In order to achieve that goal, you would want to use another flow (such as the authorization code grant) in which the user directly provides credentials to the authorization server.

Thus, with OAuth2, one would ideally not use ROPC in such cases rather use a different one, such as authorization code flow. This protects any application from knowing the user's credentials which are presented only to the authorization server. Thus, a user's credentials are not leaked. The same issues apply with basic authentication, but in the next section, I will explain how ROPC is still better because the user's credentials still do not need to be stored by the client in ROPC for persistent access by the clients.

Note that when the user goes to the authorization server, the authorization server can also ask user to confirm that they want to allow the client to access the resources on their behalf or not. That is why it is called the authorization server because the process of authorizing a client to access resources is entailed in the process. If the user does not authorize the client, it will not get access to the resources. Likewise, if the user themselves do not have access to the resources, the authorization server can still deny access and not issue a token.

In basic authentication, even the authorization server and resource server are combined into a single entity. Thus, the resource server wants to authorize the user, so asks the credentials from client. The client furnishes those credentials which are used by the resource server to authenticate the user. This means that multiple resource servers will essentially be requiring credentials from the user.

Token issuance

The clients get tokens from authorization server, keep them around and use those to access the resources (more details on tokens themselves below). The clients never know the user's password (in flows other than ROPC) and do not need to store it. In ROPC, even though the clients do know the user's password, they still do not need to store it because they use these tokens to access resources. By contrast, in basic authentication, if a client does not want to have user to provide credentials in every session, then the client has to store the user's password so they can furnish it the next time around. This is a major drawback to using basic authentication unless the client is only a web application in which case, cookies can address some of these concerns. With native applications, that's usually not an option.

There is another aspect of OAuth2 which is entailed in how tokens are issued and they work. When a user furnishes credentials to the authorization server (even in ROPC), the authorization server can give one or more of the two types of tokens: 1) access token, and 2) refresh token.

Access tokens are sent to the resource server which will grant access to the resources after validating it, and usually they have a short lifetime, e.g. 1hr. Refresh tokens are sent to the authorization server by the client to get another access token when it expires, and usually have a large lifetime (e.g. a few days to months or even years).

When the client provides the access token to the resource server, it looks at the token and after validating, looks inside the token to determine whether to allow access or not. As long as access token is valid, the client can keep using it. Let's say the user closes the application and starts it the next day, and the access token is expired. Now the client will make a call to the authorization server and present the refresh token assuming it's not expired. Authorization server, since it already issued the token, verifies it and can determine that the user does not need to provide the credentials again and thus gives another access token to the client. The client now has access to the resource server again. This is how typically the client applications for Facebook and Twitter ask for credentials one time and then do not require the user to provide credentials again. These applications never need to know the users credentials and yet can access resources every time user starts the application.

Now the user can go into the authorization server (e.g. in their Facebook user profile), change password without impacting any client applications. They will all continue to function properly. If the user loses a device on which they already had an application with refresh tokens, they can tell authorization server (e.g. Facebook) to "log them out" of those applications which the authorization server (i.e. Facebook) will accomplish by not honoring any existing refresh tokens and forcing the user to provide credentials again when they try to access resources through those applications.

JWT is simply the token format that is usually used with OAuth2 and OpenID Connect. The methods of signing the token and validating it is also standardized with libraries available for those instead of every resource server implementing yet another solution. Thus, the advantage lies in reusability of code that has been vetted and continues to be supported.

Security implications

Basic authentication will be weaker when any of the above scenarios are in the picture. There is also an extensive threat model for OAuth2 available for developers who can use the suggestions in it to avoid common vulnerabilities in their implementations. If you go through the threat model, you will see that many implementation related vulnerabilities (such as open redirector and CSRF) are also covered in it. I did not go through comparison of those against basic authentication in this response.

The last major advantage of OAuth2 is that the protocol is standardized and multiple authorization servers, clients and resource servers honor it. Numerous libraries are available to developers, which are maintained so as security issues are found in implementations, the libraries are updated while allowing interoperability.

Conclusion

If you are writing a new application, IMO, the ideal case would be to avoid both the basic authentication and ROPC because of the issues inherent in them. However, each application has different needs, timelines, developer proficiency etc. so the decision is case-by-case. But even if you did not have any more need than basic authentication, by choosing it, you could lock yourself into an architecture that may not be easy to extend (e.g. if you have multiple servers in the future, you would not necessarily want to have the user provide credentials to each one of them rather just provide to authorization server once, which can hand out tokens, etc.)

Note that I did not address your comment about how the credentials are sent over the wire because those can be secured using TLS or a similar protocol, or proof of possession etc. As someone already suggested, base 64 encoding is 0 security, please do not be deluded by that. The differences mentioned above are usually at the architectural level and thus that is where I focused because architecture is the hardest to change once implemented.

Azure Active Directory B2C Basic, a service which I work on and was recently released for public preview, allows third party application to use AAD as the authorization server with interoperability with social IDPs (such as Facebook, Google, etc.). It also allows users to create their own accounts instead of using social IDPs and those can later be used for authentication purposes. There are a few other services also like that (e.g. another one I know of is auth0) which can be used by developers to completely outsource authentication and user management for their applications and resources. The same protocols characteristics that I mentioned above is used by developers to decouple authorization server (AAD), a resource (e.g. their REST APIs), the client (e.g. their mobile applications), and users. I hope this explanation helps somewhat.

2
  • Thanks for a wide angle, but I don't think these advantages, (a) letting the user agent hold just the token instead of the password, (b) allowing a password change without disrupting existing client apps, (c) allowing users log out other sessions are specific to token authentication flows. Neither Basic nor token authentications mention functions (b) and (c) in their specs. Implementing (b) and (c) seems possible for any kind of authentication. It would involve keeping track of passwords (preferably their hashes). The advantage (a) seems dependant on the wider scope of the password.
    – eel ghEEz
    Feb 26, 2019 at 20:23
  • 1
    How could we use OAuth if user (Resource Owner) doesn't have any credentials with an external Authorization server, but he has credentials in the Client application? That is we have Resource Owner (user), The Client (representing the user & also containing credentials for user) and Resource Server. How can a Resource Server authenticate & authorize the user? Mar 14, 2019 at 6:13
3

I believe you are misinformed about the encryption around GET variables in a URL

The only people that can view the GET variables in a request are the original computer and the receiving server (link).

Only the DNS lookup based on the domain the HTTPS request is sent to is not encrypted. Everything else, the ports, the GET variables, the resource ID, is encrypted.

The only caveat to that is that the receiving server may log out the full request path, but you are in control of that so you can protect that data however you see fit.

3

Basic authentication is not a good way to secure your REST API. I explained the reasons why in this answer.

When you build a REST API, you are implementing the resource server in OAuth2 terms. All your API needs to do is validate that the token passed along with the request in the Authorization HTTP header is valid and from a trusted issuer. See this link for steps how to implement validation if there's no library available.

How your client acquires the token from the authorization server depends on what kind of client it is. Remember, you need to specify the type of client your going to use when you register the client with the authorization server.

In case of a web application talking to your server, it could use the authorization code grant. If it's an untrusted client like a mobile application or a JavaScript app, it should use the implicit grant.

For backend services which can't interact with a resource owner, you can use client credentials grant. For command line tools, you could use either client credentials or the resource owner password grant.

It all depends on what kind of client you are using.

Finally, validating a JWT token happens on the resource server without the need to talk to the authorization server. This leads to a better scalable architecture then solutions that need to look up private data for each client.

1

It's either secure or not secure. No more, no less. Having base64 doesn't make Basic Auth (or anything) more secure.

There's nothing wrong in sending anything unencrypted if it's using encrypted pipe like Https.

OAuth has more features, use it if you need it. For anything else, e.g. banking, using basic challenge-response is fine and secure.

0

I think you need to understand the terminologies first. You are comparing- Authorization and Digital signature

OAuth is open standard for Authorization, where as what amazon is doing (as per the article and details provided in your question) is creating a valid digital signature which gives a recipient (here Amazon) reason to believe that the message was created by a known sender, that the sender cannot deny having sent the message (authentication and non-repudiation)

For which authorization mechanism to use, it more or less depends on your use-case.

Below is what can be found on StackOverflow here:

Basic authentication which requires a very simple hashing in order to calculate the single required header - OAuth is without a doubt a more expensive authentication. The important thing to realize is that the two authentication mechanisms serve entirely different purposes. Basic Auth is for authenticating a client to a primary application. OAuth is for authorizing a third party to access client data from a primary application. Both have their place and selecting one over the other should be driven by the particular use case of the implementation.

And here is another interesting article comparing the two.

Basic Authentication over SSL is actually fairly responsible, from a simplistic security standpoint. When we’re contending with usernames and passwords, Basic auth is a prevalent solution as it’s so easy to implement. The transmission of credentials is encrypted over SSL, and use of the “Authorization” header is ubiquitous in HTTP clients and systems.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.