We’ve taken a close look at OAuth 1 clients; this chapter will focus on the OAuth 2 client. OAuth 2 provides solutions for the same type of authorization problems OAuth 1 solves, it just does it in a slightly different manner. OAuth 2 is really more of a framework than a single protocol.
There are times when we’ll want to pull user content or resources from a third-party site into our application. For reasons described earlier, we don’t want to have to manage, store, or know our user’s credentials; nor do we want to have provide those credentials to a third-party service whenever we want their content. Doing this puts an unreasonable responsibility on us to ensure we’re the only other people who know these user name and password combinations.
In addition, our users are not going to be happy if they have to change the credentials for a single service on more than one site. Happy, well protected users are going to ensure they continue to use our application and aren’t scared away because of security or inconvenience.
If you’re like me, you’ve always wondered why OAuth 1 was so difficult to understand, yet did very little to help solve the always tricky authorization problem. Authorization, in short, is making sure your users can see what they’re allowed to see and not allowing unauthorized users to see the same protected content. Obviously, protected content and how it is defined differs from application to application, but in short, someone who isn’t me or a person I’ve authorized (by friending, following, etc) shouldn’t be able to see my files, likes, pictures, and so on. Due to the variant nature of applications, it would be very difficult to come up with a universal access control system which would work for everyone. It would be so difficult and the implications of failure could be so disastrous, it’s really not even worth attempting.
OAuth 2 can, however, provide more control over what is available to an authenticated user in a given application. I’m sure we’ve all seen an authorization page which asks us if we want to connect to this application, but if you look closely it will also tell you what the application has access to. Consider Twitter as an example, you have read or read-write access across the board. Your application can either read all the protected resources or read and create content in all the protected resources. This might be acceptable for your application, but how would we handle restricting users from accessing direct messages? Long story short, we can’t.
Scopes can allow the application to determine what specific resources the access token is authorized to use, and how they are authorized to use them. Keep in mind, the application is still responsible for building the mechanisms to manage these scopes, so it’s still something you would have to consider when using or building with OAuth 2. Basically, we’re exchanging the model of “read and/or write everything” for a more specific model which asks, “what do you want to have read and/or write access to?”. As a prime example, take a look at the GitHub API; they require scopes when requesting access tokens and have a pretty detailed list of the resources you can manage. GitHub provides the following scopes:
This isn’t the complete list; it can be found at GitHub API Scopes1.
From the few I chose to detail, you can see a much finer level of access control managed with the tokens. It’s very likely the management of public keys or the ability to delete repositories might not be something your application really wants users to do. By providing a list of scopes when you make your authorization request, you can effectively limit the use of the API to perform those actions. In a sense, it provides a little bit more clarity to the authorization flow and how it can be managed on the server.
Scopes are only used in the process where we are retrieving tokens and can (but don’t have to) be used in the generation of the actual access token. Any calls which made to protected resources do not require those scopes to be passed along or maintained from call to call. They become strictly part of the authorization and authentication process. The service provider will verify the scopes allowed for any given access token.
We’ve taken a cursory look at how the authentication flow works, but as you might suspect, there’s more to it than that. We’re starting to approach usability, but it’s important to understand the specifics on how we retrieve our access tokens, what implications it might have, and–if we have a choice–when to use which type of grant. We’re going to be covering that next.
Up to this point, we’ve covered this whole authentication flow process from a really basic standpoint. While it’s good to understand the basic flow of things, it’s equally important to understand the specific mechanisms which make this flow work. In this section, we’re going to cover the grants we can use to retrieve our access token. If you recall from he OAuth 1 Client chapter, we were given an access token and an access secret. We needed both to build the signature. In this model, we’re only going to be retrieving one token, the idea of the access secret goes away. Because of this, don’t be surprised if you are unable to see the actual access token in the third party application settings. This token should be be treated with the same sensitivity as a password and not be shared with the world at large.
The Implicit Grant is a little bit different than the Authorization Code Grant. The process starts out the same, where the user is directed to an authorization endpoint where they will login with their credentials. Once authenticated, the user will be redirected, but the access token is provided on the first redirection. There is no temporary code exchange required to retrieve the access token.
While there are fewer steps in this process, it should generally only be used in situations where the access token cannot be stored securely. This token should be treated as public knowledge, and it’s advisable to not allow any overly destructive permissions to be carried out via this token. The Implicit Grant also doesn’t allow for refresh tokens to be distributed, since they would be potentially publicly available as well. In order to retrieve new tokens, the authorization process must be completed again.
In the last two grants, we’ve seen how we’ve been redirected to the third-party website to authenticate and authorize the application. This third kind of grant does not utilize redirection at all and is therefore pretty scary to consider using. In fact, the RFC states it should only be used when there isn’t a viable alternative. In this scenario a POST request is made to the authorization server and the following fields must be present in the request: grant_type
set to 'password'
, username
, and password
. Additionally, scopes can be set the same way as described earlier in the chapter. The authorization server is required to only store the sent credentials until an access token is provided, at which point it cannot store them. Keep in mind, this requirement is only in place to remain OAuth 2 compliant, there is no actual mechanism forcing the server to remove your credentials.
You can probably see how scary this is, just based on the fact you are sending your username and password. The specification requires this POST request to be sent over with Transport Layer Security (TLS). But keep in mind this sends your user’s password directly in the request.
I just want to take another opportunity to be cautious when considering this grant. The reason is simple: tokens are generally short-lived and easily revoked. If a token is compromised, it can be invalidated very quickly. When a password is compromised, a user is open to all the same issues as a compromised token. In addition, the attacker now has access to the user’s account on the third-party service. This could allow for passwords to be changed and accounts to be hi-jacked. Only use this grant in a situation where there is an extremely high level of trust and even then only if you absolutely must.
While it can be dangerous, it is a valid grant type in OAuth 2 and it’s important to understand some of the concerns associated with using it. With any application, it’s very important to follow secure password practices in order to maintain your users’ online security. Ideally, users would have longer passwords with varying character types (letters, symbols, numbers, etc.) and would not use the same password on more than one application. Any problem posed by a password being leaked out can be magnified if one password allows access to other online accounts.
The last type of grant we’ll be covering is the Client Credential Grant. Similar to the previous kind of grant, it requires the sending over of a different set of credentials. As with the previous grant, this should only be used by clients who are not public facing. When implementing this grant, the client_id
and client_secret
are used as opposed to the resource owner’s credentials. The client_id
and client_secret
are the values which are used to identify the application, so it goes without saying, these values need to be protected from the outside world. They can be used for a service having no outside access, a private network for example, and where the ID and secret can be shared with little to no risk.
To use this grant, a request has to be made to the token endpoint with a parameter for the grant_type
set to 'client_credentials'
and, optionally, a list of scopes. To send the ID and secret along, you can use an Authorization
header which utilizes Basic
authentication. Basic authentication is created when the identifier and secret are combined and separated by a colon. So for example if my client_id
is '123'
and my client_secret
is 'abc'
, you would start with the string '123:abc'
. This value is then base64 encoded and added to the authorization header. If those values are authenticated, then an access token is returned. Below is a value of what the Basic Authorization header would look like, with a place holder for the encoded value.
Authorization: Basic <base64 encoded identifier:secret string>
It’s very simple; of course, since they have to be authenticated they have to be encoded and not hashed. This means anyone with access to the string can base64 decode it and get access to the original information. PHP provides a function to do this called, base64_decode
. For this reason, I’d stress again you should only use this in confidential situations.
Obtaining the access token is the most involved part of this process. Unlike OAuth 1, there isn’t a lot we have to do to identify ourselves to protected resources once we have it. The simplicity of OAuth 2 makes it a bit easier to use on a request to request basis. The trade off is the access tokens tend to have a much shorter life than the access credentials in OAuth 1.
The service will return a token and token type upon the successful request for access tokens. It’s important to check with the service you are using to see how the service requires the token to be presented. Some services state you should put them in the URL, while others have different token types which are required for use in the Authorization header. There will be more on this in the OAuth 2 implementation chapter. For example, GitHub documentation says to use the following:
Authorization: token <token>
Other examples replace the word token with bearer
and for an example of a service which states to use it as a query parameter, we can take a look at Foursquare:
https://api.foursquare.com/v2/users/self/checkins
?oauth_token=ACCESS_TOKEN
There’s no single way to present the token in a request. The important aspect is that it’s presented in a way the resource server can access and identify the token. Always be sure to check the documentation for any differences in how to present your token. Also in addition to the examples listed above, it’s possible there are other methods for presenting the tokens which are specific to a particular service.
3.144.161.116