Sei sulla pagina 1di 17

The (Almost) Definitive Guide to OAuth with Tyk

The (Almost) Definitive Guide to OAuth with Tyk 1


What is OAuth? 2
Which grants does Tyk support? 2
Authorization Code 2
Password 2
Client credentials 2
Refresh token 2
Tyk, API Gateways and OAuth 3
So, how does a gateway fit in? 3
How does this work? 3
Client credentials: 4
Create the API Definition 4
Create a policy 5
Create an OAuth Client 5
Requesting a token 6
Password grant 7
Set up an API to use the Password Grant: 8
Add the API to an existing Policy or create a new one 8
Create a new OAuth Client for this API 8
Create a user 9
Use the refresh token 10
Authorization Code Grant 11
Create an API with the Authorization Flow 11
Create a policy 12
Create an OAuth Client 13
Run an Authorization request 13
Imagination Time: Assume the user logs into the application 14
Exchange the auth code for a token 15
Notifications 16
Miscellaneous notes 17
What is OAuth?

The OAuth standard is a set of authentication protocols designed to make it easy to federate
and standardise authentication and authorization between applications. In particular, federating
authentication to other providers in order to solve the problem of having “too many logins”.

For example, when logging into your Trello account with Google, you are actually using OAuth
to do so.

OAuth comes in two flavours: v1 and v2, we are only going to talk about v2, because v1 isn’t
supported at the moment.

We’re not going to discuss the various flows and grants here, if you would like a refresher on
what they are, how they work, and when to use each, there is an excellent guide ​here​.

Which grants does Tyk support?

Tyk supports most grant types, though not all flows are fully supported. It is also worth noting
that scopes are not processed at all at the moment, deferring that responsibility to security
policies instead.

Authorization Code
This grant enables an authorised client to generate an authorization code for a user, and then
trade that authorisation code for an access token.

Password
This method will authenticate a user directly in a trusted app and trade a username and
password for an access token

Client credentials
This mechanism is for machine-to-machine grants where the user’s permission is not required
because the service is trusted.
Refresh token
This only works with the Authorization grant type, and will issue a refresh token to the
requesting client so that they can request new access tokens without having to go through an
authentication procedure again for the end user.

Tyk, API Gateways and OAuth


The tricky thing with OAuth is that it always assumes that there are four main parties involved:

1. The client: The application that is requesting access, e.g, your third-party twitter app
2. The resource owner: The user, or the identity whose data is being requested
3. The resource server: The API or service that has the relevant resources that are being
requested
4. The authorization server: The service providing the authorisation for the resources

Nowhere in this flow do you see an intermediary API gateway that is mediating access between
the resource server and the authorisation server.

What most OAuth implementation and guides expect a resource owner to do, is to implement an
OAuth library to manage the callbacks and checks to allow access. It’s not something that can
be easily bolted on.

So, how does a gateway fit in?

The way Tyk handles this problem is by providing it’s own OAuth server. So it can act as the
Authorisation server in the above list, but it allows for a callback/redirect that minimises the
integration requirements on the part of the resource owner, since Tyk itself does not provide “log
in” screens, and it also makes no sense for Tyk to own the authentication piece for an existing
services user base.

So to put it very simply: what Tyk does, is it provides all the infrastructure of an OAuth solution,
with some simple hooks to allow for easy integration for a user that wants OAuth but not the
overhead.
How does this work?
The Tyk OAuth server will handle:

- Client registration
- Auth code creation
- Auth code trades for access tokens
- Refresh token generation
- Refresh token trades for access tokens
- Client and Password grants

For client and password grants, since there is no third-party authentication (a user does not log
into a web app), the flow is very simple and no integration is required. For Auth code grants it
gets a bit more complicated.

We’ll start with the simple ones, please note that we aren’t going to repeat all of the examples in
these steps for all grant types, we’ll just reference them as we go through, so it’s worth reading
from the start!)

Client credentials:
This flow literally just needs the credentials of the accessing client in order to proceed, these are
sent both as form parameters and as an Authorization header using the Basic Auth format. Tyk
will respond with an access token.

Create the API Definition


To start things off, you will need to create an API that supports this flow, this is pretty simple,
just add a new API and set the Authorisation section as follows:
We have enabled the “Client credentials” grant, and are allowing “Tokens”

The remainder of the form is not actually required since there are no redirects in this flow.

Create a policy
Next, we will need to create a policy for this API, this is a standard operation and the same as
any other policy creation, so we’re not going to go into detail here.

Create an OAuth Client


In order for any of these requests to work, you will need a valid OAuth client. Clients are stored
in the gateway​ the same as tokens, this is because they need to be quickly looked all the time,
so having them elsewhere would be inefficient.

To create an OAuth client, brows back to your API list, for the API you have created, you will
now see a new OAuth clients button:
Click this and add a new client:

We don’t actually need a redirect URI​ It’s important to add a redirect URL, even if it is just a
dummy value, we ​do​ need to select the policy we created earlier. THis policy will be applied to
each token that gets generated by this client ID.

Once the client is created, we can browse to it and view it’s ID and secret in the detail view.
Requesting a token
Now that we have all the required components in place, we can request a token, here’s an
example curl request:

curl -X POST \

https://YOUR-TYK-CLOUD-ENDPOINT.cloud.tyk.io/clientcredentials/oauth/
token/ \
-H 'authorization: Basic b64(clientid:secret)' \
-H 'content-type: application/x-www-form-urlencoded' \
-d
'grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret
=CLIENT_SECRET'

The important things to note here are:

- /oauth/token/​: This is a reserved endpoint on the API slug that provides the
authentication endpoint (the trailing slash is required, otherwise it will ask for
authentication)
- Authorization header: This takes the form of “​Basic
b64encode(client_id:secret)​”
- Form data: ​grant_type​: set to ​client_credentials
- Form data: ​client_id​: The ID of the accessing client
- Form data: ​client_secret​: The secret of the accessing client

That’s all that is needed, Tyk will then respond with an access token that you can use:

{
"access_token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"expires_in": 3600,
"token_type": "bearer"
}

You can now use this token to access the API.

Password grant
The password grant is very similar to the client credentials grant, but it uses a username and
password instead of a client ID and secret (these are still required though).
Set up an API to use the Password Grant:

Again the redirect and secret are not strictly required since this grant does not use them

Add the API to an existing Policy or create a new one


We need to make sure that the client can get access to the API, so we need to make sure the
policy has been properly updated.

Create a new OAuth Client for this API


Currently, each API must have it’s own OAuth Clients, they can’t be shared between APIs. This
means we need to create an OAuth client, with a redirect URI, even if it’s not being used, you
may get validation issues if this is missing.
Create a user
Since this is a credentials based auth, we need to create a new basic auth user in Tyk, you can
do this by going to the Key section and adding a new Key, then setting it to be a “Basic Auth”
user, and assigning a username and password:

Make a request for a token

This format is very similar to the previous request, but need to ensure we have the correct
settings applied:

curl -X POST \

https://YOUR-TYK-CLOUD-ENDPOINT.cloud.tyk.io/password-grant/oauth/tok
en/ \
-H 'authorization: Basic b64(clientid:secret)' \
-H 'content-type: application/x-www-form-urlencoded' \
-d
'grant_type=password&client_id=YOUR_CLIENT_ID&username=john%40smith.c
om&password=test123'

As you can see, we have the same endpoint as with the client credentials flow, and we use the
same style of Authorization header which represents the client.

The key differences are:


- The username and password are sent as form parameters
- The client secret is not explicitly sent
- We have specified the ​password ​grant as the grant type

This will then yield an access token for the API:

{
"access_token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"expires_in": 3600,
"refresh_token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"token_type": "bearer"
}

Notice that with this grant we get a refresh token, this is so that we do not need to keep sending
the user credentials over and over again to get a new token for this user. In the case of a mobile
app this can be very useful.

However, in order for this to work, you will need to enable refresh tokens as a grant in the API
configuration (see above, we did not do this in our demo).

Use the refresh token

Once you have enabled it, you can request a refreshed token using the same endpoint:

curl -X POST \

https://YOUR-TYK-CLOUD-ENDPOINT.cloud.tyk.io/password-grant/oauth/tok
en/ \
-H 'authorization: Basic b64(clientid:secret)' \
-H 'content-type: application/x-www-form-urlencoded' \
-d
'grant_type=refresh_token&client_id=YOUR_CLIENT_ID&refresh_token=XXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXX&client_secret=CLIENT_SECRET'

All we have changed here is that we have added refresh_token as a grant type, and have
re-inserted the client secret.

Authorization Code Grant


This is the most complicated mechanism, and is also the most difficult to demo, because it
assumes that there is a third-party authentication provider (e.g. a system that provides a log in
of some sort).

Here the request flow is:

1. User wishes to log into app


2. Application (client) redirects to the authentication provider
3. Authentication provider validates the client ID and secrets
4. User logs in
5. Authentication provider redirects the user to a pre-agreed redirection URL with an
authorization code as a fragment
6. The client can then call the token endpoint to exchange the authorization code for a
token (and potentially a refresh token)

Create an API with the Authorization Flow

The first step is to create an API that uses this flow, this is quite straight forward and is similar to
the steps before:
The important difference here is that we have entered a login redirect value, notification URL
and a shared secret.

1. The login redirect: This is the page that Tyk will redirect the user agent to if the authorize
request is valid (as in, it has a valid client ID and the request meets the spec for OAuth)
2. The notification URL: Will be notified every time a token is generated by this client, this is
to enable any upstream server to maintain a clear idea of what tokens have been
generated.
3. The secret: Is to ensure that the notification came from the Tyk gateway

Create a policy
Once the API has been created, do the same as before, and create a policy that grants access
to this API
Create an OAuth Client
As before, we need to create an OAuth client, this time though we need to set a redirect URL,
this is the pre-registered redirect URL that is part of the OAuth spec, in a standard scenario, the
authorization server will redirect the client to this URL, they must match in the inbound request,
and what Tyk has on file.

Run an Authorization request


We can’t simulate this flow easily with just a few cURL commands, so some imagination will be
required for this next step.

The client will send the user to the authorization endpoint:

martin@DESKTOP-OKR0UFG ~/> ​curl -v -X POST \


https://YOUR-TYK-CLOUD-ENDPOINT.cloud.tyk.io/authorization-code-grant/
oauth/authorize/ \
-H
'content-type: application/x-www-form-urlencoded' \
-d
'client_id=YOUR_CLIENT_ID&redirect_uri=https%3A%2F%2Frequestb.in%2Fyuq
qwoyu&response_type=code'
* Hostname was NOT found in DNS cache
* Trying 52.72.245.24...
* Connected to YOUR-TYK-CLOUD-ENDPOINT.cloud.tyk.io (52.72.245.24)
port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using ECDHE-RSA-AES128-GCM-SHA256
* Server certificate:
* subject: CN=*.cloud.tyk.io
* start date: 2017-02-06 00:00:00 GMT
* expire date: 2018-03-06 12:00:00 GMT
* subjectAltName: YOUR-TYK-CLOUD-ENDPOINT.cloud.tyk.io matched
* issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
* SSL certificate verify ok.
> POST /authorization-code-grant/oauth/authorize/ HTTP/1.1
> User-Agent: curl/7.35.0
> Host: YOUR-TYK-CLOUD-ENDPOINT.cloud.tyk.io
> Accept: */*
> content-type: application/x-www-form-urlencoded
> Content-Length: 111
>
* upload completely sent off: 111 out of 111 bytes
< HTTP/1.1 307 Temporary Redirect
< Cache-control: no-cache="set-cookie"
< Content-Type: text/plain; charset=utf-8
< Date: Thu, 13 Jul 2017 04:46:07 GMT
< Location: http://my-app-login-page.com
< Content-Length: 0
< Connection: keep-alive
<
* Connection #0 to host YOUR-TYK-CLOUD-ENDPOINT.cloud.tyk.io left
intact

As you can see form the request above, we sent a request to /oauth/authorize/ and then the
gateway, after validating the request, sent us on to the login redirect page that we specified in
our API definition.

Note that this request can also be done as a GET, this is because not all user agents support a
307-redirect, which instructs the user agent to retain the initial method of the request.

Imagination Time: Assume the user logs into the application


What happens after this redirect is that this data has been forwarded on to the authorizing login
page. All this page needs to do is:

1. Capture the data that has been forwarded (the client ID, redirect URI and code request)
2. Log the user in
3. If the user has logged in succesfully, send a callback to Tyk with exactly the same data
that it just captured, just to a private endpoint

We can simulate this step with cURL again:

curl -X POST \
https://admin.cloud.tyk.io/api/apis/oauth/0ddf90df9d2743fa5a3bb15d60e
b1ca7/authorize-client/ \
-H 'authorization: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' \
-H 'content-type: application/x-www-form-urlencoded' \
-d
'client_id=YOUR_CLIENT_ID&redirect_uri=https%3A%2F%2Frequestb.in%2Fyu
qqwoyu&response_type=code'

There are some very important points to note here:

1. The URL in this case is the dashboard API, and in particular we are sending this request
to the API ID of the service in question, this is not the ID that you see in the URL of the
API Designer page, it is the API ID that is encoded in the API Definition and that is used
by the gateway
2. The Authorization header here is the auth header for a dashboard user
3. Otherwise, we are sending the same data that we sent before (the captured data)

This callback, when run, will yield the following:

{
"code": "XXXXXXXXXXXXXXXXXXXXXXX",
"redirect_to": "https://requestb.in/yuqqwoyu?code=XXXXXXXXXXXXXX"
}

The authorizing application / log in page, should redirect the user to this page, this is the URL
that was set up as part of the Client as the redirect URI and is where the user will be returned to
so the client application can pick up the authorization code.

Exchange the auth code for a token

The client will now use the authorization code to request an access token, this is very similar to
before:

curl -X POST \

https://YOUR-TYK-CLOUD-ENDPOINT.cloud.tyk.io/authorization-code-grant
/oauth/token/ \
-H 'authorization: Basic b64(clientid:secret)' \
-H 'content-type: application/x-www-form-urlencoded' \
-d
'grant_type=authorization_code&client_id=YOUR_CLIENT_ID&code=TP2Z-js_
RCedmB0PyX_9sQ&redirect_uri=https%3A%2F%2Frequestb.in%2XXXXXXXX'

Here we need to authorize as the client (basic auth Authorization header), send the code along
with our client ID, and include our redirect URI.

This request will only work once, authorization codes are single-use, so a new one needs
generating if it has been used, also, if it has not been used and the client generates another
code, the old code will be revoked.

The response from this will be an access token:

{
"access_token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"expires_in": 3600,
"refresh_token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"token_type": "bearer"
}

As discussed earlier, the refresh token can then be used to generate new tokens when the initial
token has expired.

Notifications

In the above Authorization Grant flow, we used a notification URL, this gets notified each time a
token gets generated, the data it will receive looks like this:

{
"auth_code": "XXXXXXXXXXXXXXXXXXXXXXXX",
"new_oauth_token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"refresh_token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"old_refresh_token": "",
"notification_type": "new"
}

The reason we send this data is so that a monitoring application can keep track of the chain of
auth code that have been generated for a user in case it needs to be invalidated.
Miscellaneous notes

- The authorization flow callback can also be done directly against the gateway, it is the
same format of request, but the endpoint is different and the gateway secret must be
used instead of the Dashboard User token
- The authorization flow callback also supports an additional form parameter called
key_rules​, this is a stringified version of a Session Object. If an integrator does not
wish to use the same policy for all their clients (or for all tokens generated by a client),
for example, if they wish to make use of the OAuth “scope” parameter, then they can add
this to the callback, and it will be used to generate the token instead of the policy. This
can be useful for very fine grained control over token access.

Potrebbero piacerti anche