The Authorization service implements the OAuth 2.0 protocol. It handles merchant authorization of external integrators and issues access tokens used by authorized clients to call the other parts of the iZettle API.
The OAuth API implements the OAuth 2.0 Authorization Framework (RFC 6749). For an external integrator, there are two different grant types that are of interest, the authorization code grant and the password grant. Both grant types are described below.
The authorization code grant is to be used for public integrations, where you want to create an integration that can be used by any iZettle merchant, whereas the password grant is to be used when you are creating a private integration, for your own merchant account. Please note that for private integrations, this will probably change in the future and another - simpler - solution will be made available where you can create your own access token directly from your merchant dashboard without using the OAuth API.
For public integrations, you should implement the authorization code grant as described below. This will allow any user to authorize and install your integration.
The different steps involved in the authorization flow are described below.
RFC 6749: 4.1.1. Authorization Request
Once the partner is registered and has received a secret and client id (uuid) it can present the user with a link to authorize the partners access to the users data, this link is opened up in a web browser:
{{URL}}/authorize?response_type=code&client_id=c55de605-48b6-42ef-b69e-cd9d14ded15a&scope=READ:FINANCE%20READ:PURCHASE&redirect_uri=https://httpbin.org/get
If the user doesn’t have a valid SSO token cookie, the user is forced to login. When authenticated the user is presented with a screen where the partner info is displayed, along with the requested authorization scope.
To allow the authorization, the user will press the Approve button, thus invoking the authorization URL above with an extra query parameter action=authorize
.
curl --write-out %{redirect_url} -s \
-H 'Cookie: iz_sso=9c3375c9-fd1b-4fde-9743-6f3d2e475388' \
'{{URL}}/authorize?response_type=code&client_id=c55de605-48b6-42ef-b69e-cd9d14ded15a&scope=READ:FINANCE%20READ:PURCHASE&action=authorize&state=XFadwMEXCJGJUfD'
The server responds with a redirect to the redirect URI that the partner has provided, appended with the generated authorization code as a parameter code
:
http://httpbin.org/get?code=4fa87ba8cc7f30e91ad2ab1ad21c1b3e&state=XFadwMEXCJGJUfD
The 'redirect_uri' parameter is provided by the partner and is where the user will be redirected after a successful authorization. Only URIs registered with the partner application are allowed.
The state
parameter will be carried unchanged through the authorization flow, what the partner set in the state
parameter when constructing the authorization URL will be available at the end when the user is redirected back to the partner. This makes the state
parameter usable for mitigating CSRF attacks by setting a unique value for the request and then validating that you get the same value back.
The state
parameter can also be used to restore the previous state of the application, for example setting the URL that the user is intended to reach after the authorization request.
RFC 6749: 4.1.3. Access Token Request
Once the client has received the authorization code in the redirect it can use this code to request the unique access and refresh tokens used when accessing the APIs:
curl -s -d \
'grant_type=authorization_code&redirect_uri=http%3A%2F%2Fhttpbin.org&code=4fa87ba8cc7f30e91ad2ab1ad21c1b3e&client_secret=7356b8a1-75ac-4336-970b-bef63cd219c1&client_id=c55de605-48b6-42ef-b69e-cd9d14ded15a' \
-H'Content-Type: application/x-www-form-urlencoded' \
'{{URL}}/token' | python -m json.tool
The response will contain both the access and refresh tokens:
{
"access_token": "eyJraWQiOiIxNDQ0NzI3MTY0Njk4IiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJpWmV0dGxlIiwiYXVkIjoiQVBJIiwiZXhwIjoxNDQ0ODI1MzI1LCJqdGkiOiJXeE1vXzFaNFJQMWQ5Mi10N2owUXBRIiwiaWF0IjoxNDQ0ODIzNTI1LCJuYmYiOjE0NDQ4MjM0MDUsInN1YiI6IlllemNseEJlVHBLUDBqNXRBdmdqWXciLCJzY29wZSI6ImFsbCJ9.O-mh4Wyt-ReS-5tH2YBN2CVh1-UnyMf2xoF6Qie3pa2YGZY_u2UTU2bp0KiGjmHHLgYI5c9N1F6s7Ze-KpAyH1WZHSW8mezt25qBLpvCgr4OFkRGY7QYVa-UhVXkQ0B_shviiwubenTNCGdQl9fJlJmElqb5SQl2Tl7sraKV4T1cp5dpPZmA7AeeMaEnooQ2STluF76AcRipMq9aCFzGKv-MrfNhpl6wUwhxaMXtF9SSr8emWf5MEoGfm1mjPpV6J6LmHQtkQN2VJLy81BIGiDGtS_dhvdPMyS2O3dDLTA-LJSA_q4ZdbEsEbomCyfMDvS6RE_mnI06lW8dYMQ7yZA",
"expires_in": 7200,
"refresh_token": "IZSEC07b0edfc-f557-4e52-a995-384288e2351e"
}
For private integrations, you should implement the password grant as described below. This will allow you to retrieve an access token for your iZettle account.
NOTE: In the future, this process will probably change, allowing you to create an personal access token directly in your merchant dashboard.
RFC 6749: 4.3.2. Access Token Request To obtain an access token that can be used to call our APIs, you will have to send your client credentials, as well as your iZettle username and password to the OAuth service, like this:
curl -s -d \
'grant_type=password&client_id=c55de605-48b6-42ef-b69e-cd9d14ded15a&client_secret=IZSEC7356b8a1-75ac-4336-970b-bef63cd219c1&username=user@email.com&password=mypassword' \
-H 'Content-Type: application/x-www-form-urlencoded' \
'https://oauth.izettle.net/token'
You will get a normal access and refresh token back, which you can then start using.
RFC 6749: 6. Refreshing an Access Token
The access token has a lifetime of 7200 seconds (120 minutes). Once it has expired the client needs to request a new access token using the refresh token:
curl -s -d \
'grant_type=refresh_token&client_secret=7356b8a1-75ac-4336-970b-bef63cd219c1&client_id=c55de605-48b6-42ef-b69e-cd9d14ded15a&refresh_token=07b0edfc-f557-4e52-a995-384288e2351e' \
-H'Content-Type: application/x-www-form-urlencoded' \
'{{URL}}/token' | python -m json.tool
The response has the same format as the request above:
{
"access_token": "eyJraWQiOiIxNDQ0NzI3MTY0Njk4IiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJpWmV0dGxlIiwiYXVkIjoiQVBJIiwiZXhwIjoxNDQ0ODI1NTk5LCJqdGkiOiJzRXlEQ2JOS1d1dWhqN2FadGxibnJnIiwiaWF0IjoxNDQ0ODIzNzk5LCJuYmYiOjE0NDQ4MjM2NzksInN1YiI6IlllemNseEJlVHBLUDBqNXRBdmdqWXciLCJzY29wZSI6ImFsbCJ9.RtbbSu68fMMGssQHIhdLF6Sa4nFeBkMDSQkDsVYxaKa0jMqd6i6Dl9W1C4XJdnNdNiuke6fG5dGGSB6yR6mx5qXJcEBl8bwUTp7r1jX3n9WbgXHQtwCiSx5J3wMrE3RIEGHqSeD0DkQDLaKLqlb12H1DUMK4wTFL3_KxtYqP_dEijOPtV9gN7EkZUIitWqMa3DOR2IqszldrcUXIVPkp_DRWtjvBSCsgglQFGgjyblpOQJM5CR64aD1CgyOSE6JAMWHBhbB7j7gB6DALHLh82twU9camEkCFKKra4n1Zj6mHF9DMSwccH7lpdjjSKPEUujyKCaLQRn82AH0Q8vSlKg",
"expires_in": 7200,
"refresh_token": "IZSEC07b0edfc-f557-4e52-a995-384288e2351e"
}
Note
|
Rotation of refresh tokens may be enabled at any given time. That is, when you get a new access token, you might also get a new refresh token (invalidating any previously issued refresh token). Therefore always make sure to pick up the refresh token you get in the response and use that for the next refresh request, instead of reusing the current refresh token. |
RFC 6749: 5.2. Error Response
The Authorization OAuth2 API will return errors when retrieving and refreshing access tokens as specified in the RFC, for example:
HTTP 400 Bad Request
{
"error": "invalid_request",
"error_description": "invalid refresh_token"
}
Access tokens should be included as follows:
GET /resource HTTP/1.1 Host: server.example.com Authorization: Bearer eyJraWQiOiIxNDQ0NzI3MTY0Njk4IiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ
This is described in detail in RFC 6750, section 2.1.
When using an expired or invalid access token in an API request, the resource service will return a HTTP 401 Unauthorized
response, with the error set in the HTTP header WWW-Authenticate
, similar to this:
Bearer error="invalid_request", error_description="ACCESS_TOKEN_EXPIRED"
Note: Not all services are not currently using the error code ACCESS_TOKEN_EXPIRED
as the content of the error_description
field, but rather the clear text value "The access token has expired". This will change over time and eventually all services will use the ACCESS_TOKEN_EXPIRED
.