# Part 3 - The OAuth Protected Resource
Table of Contents
What is a Protected ResourceLink to heading
A protected resource is the API that the OAuth client wishes to access. It is the API that the client is interested in accessing.
In previous blog posts, we used Facebook as an example protected resource to walk through the authorization code grant type. We will continue to do the same in this blog post as well!
ScopeLink to heading
A scope limits the level of access a client can be given to a protected resource. Let’s recap the example that we have been using since the start of our series:
- User: you 🫵
- Client: Strava
- Protected Resource: Facebook
When Strava accesses your Facebook account, the only action that Strava should be allowed to do is to make a Facebook post on your behalf. Facebook would parse the received Access Token and look for the scope field. Strava will only receive the privileges listed in the scope field. For the sake of our example, the scope field would only have the “post” value, so Strava has just enough privileges to make a Facebook post on your behalf:
scope: "post"A client can have one or more scopes assigned to it. Let’s say we also want to give Strava the permission to send a personal message on your behalf. So we would add “personal-message” scope as well:
scope: "post personal-message"Notice how the scopes are space-separated. This makes the scopes URL parameter friendly and Authorization Server agnostic.
Scope and The Authorization ServerLink to heading
When the client initially redirects the user to the Authorization Server, the client has a choice to also send a scope field with space-separated values.
When the user is redirected to the Authorization Server, the user can see what scopes the client is requesting. The user then has a choice to do the following in the Authorization Server:
- Reject the authorization request from the client.
- Remove certain scopes from the client and approve the authorization request.
- Add more scopes for the client and approve the authorization request.
This is why it is important for the scope to first be validated by the user in the Authorization Server, before the client can reach the protected resource.
Parsing The TokenLink to heading
The first step is for the protected resource to parse the Access Token. The Access Token can be sent to the protected resource as a bearer token. According to the OAuth bearer token usage specification, the bearer token can be passed to the protected resource in 3 different ways:
- The HTTP Authorization header
- Inside a form-encoded POST body
- A query parameter
The best method is to pass the token through the HTTP Authorization header because it has the least chance of being logged or leaked.
Validating The Access Token - Token IntrospectionLink to heading
The introspection request (defined in
RFC 7662) is a
form-encoded HTTP request to the Authorization Server’s introspection
endpoint, which allows the protected resource to ask the Authorization Server:
“Someone gave me this token; what is it good for?” This means the
protected resource doesn’t have to trust the token at face value. Normally
the protected resource would send a query to the endpoint path
/introspect to check the validity of the token received by the client.
This solves our problem of the client artificially elevating its permissions by manually editing the scope field. The protected resource would check on each request whether the token is valid.
Token Expiration/RevocationLink to heading
Since the protected resource now validates the token on each request, it can also check if a token has been rejected by the Authorization Server or the TTL (time to live) of the token has been reached and is now expired. If the protected resource finds out from the Authorization Server that the token is either rejected or expired, then it will not accept that token.
The Introspection EndpointLink to heading
As stated, the Authorization Server would normally accept introspection
requests on the path /introspect.
Here is what a query from the protected resource would look like once it receives a token from the client:
POST /introspect HTTP/1.1Host: authorization-server:9001Accept: application/jsonContent-type: application/x-www-form-urlencodedAuthorization: BasiccHJvdGVjdGVkLXJlc291cmNlLTE6cHJvdGVjdGVkLXJlc291cmNlLXNlY3JldC0xtoken=987tghjkiu6trfghjuytrghjThe response from the Authorization Server will normally be a JSON document that describes the token, similar to the contents of a JWT.
{ "active": true, "scope": "post", "client_id": "strava", "username": "Hamza", "iss": "http://authorization-server:9001/", "sub": "hamza", "aud": "http://facebook.com", "iat": 1775865600, "exp": 1783641600}According to our example, the scope is correct. Strava will only get permissions to post on behalf of the user Hamza. And from the time of writing this blog post, the token is also not expired.
TLS RequirementLink to heading
In a production system, proper TLS usage is a hard-and-fast requirement. TLS makes sure that a middle-man can’t tamper with the communication between two systems. TLS protects all three communication paths on OAuth:
- Client → Authorization Server (where the Access Token is issued)
- Client → Protected Resource (where the token is used)
- Protected Resource → Authorization Server (the introspection call)
For example, when a client communicates with the protected resource, without TLS, the Access Token lives in the HTTP header unencrypted. Anyone on the same network can grab the Access Token using a basic packet sniffer.
ConclusionLink to heading
The job of the Protected Resource is to validate the token, enforce the scope and trust nothing! This ends our deep-dive into the Protected Resource.