Path of Exile Developer Docs

Authorization

Almost all of Path of Exile's developer APIs require authorization of an existing Path of Exile account to use. This helps us enforce fair rate-limits as well as having a point of contact if anything goes wrong.

For this purpose we use an implementation of the OAuth 2.0 framework. This document will describe how to generate access tokens for users using your application's credentials.

OAuth 2.0

OAuth 2.0 is a popular and common way for an application to act in limited ways on behalf of a user. There are many resources online documenting the basic idea as well as frameworks that can help you understand how the process works. For this reason our implementation closely follows the original specification as well as taking guidance from some key extensions.

Users can review and revoke their tokens on their profile's applications page at any time.

OAuth Server Endpoints

Client Types

OAuth 2.0 defines two client types which we support in different ways. The vast majority of applications should use a Confidential Client.

Confidential Clients

A confidential client is backend by a secure server controlled by the application owner. These clients:

Public Clients

A public client is one without a method of securely storing any credentials. The most common example of this is an application that runs on the user's desktop. These clients:

Available Scopes

Accounts

Services

Requires a confidential client with the client_credentials grant type.

Grant Types

Authorization Code Grant (with Proof Key of Code Exchange, or PKCE)

This grant is used when your application needs access to act on another user's behalf. All authentication is done by the Path of Exile's OAuth server and no user credentials are ever shared or exchanged. The most important step is sending the user to the authorization page which presents them with the details of your request.

Flow:

  1. Start by performing the initial PKCE steps:
     // PHP example
    $base64url_encode = fn(string $value): string => \rtrim(\strtr(\base64_encode($value), '+/', '-_'), '=');
    
    $secret = \random_bytes(32);
    $code_verifier = $base64url_encode($secret);
    $code_challenge = $base64url_encode(\hash('sha256', $code_verifier, true));
    
    1. Generate a code_verifier as described in RFC 7636 Section 4.1. There should be sufficient entropy (at least 32-bytes) used to ensure the resulting value cannot be guessed.
    2. From this, create a code_challenge by base64url-encoding the SHA256 hash of the code_verifier.
  2. Generate an authorization URL and allow the user to navigate to it:
    https://www.pathofexile.com/oauth/authorize
        ?client_id=example
        &response_type=code
        &scope=account:profile
        &state=10ceb8104963e91e47a95f4138448ecf
        &redirect_uri=https://example.com
        &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
        &code_challenge_method=S256
    
    • client_id is your registered application's client id.
    • response_type is always code.
    • scope is a space-separated list of requested scopes.
    • state is a code or hash that you generate to track the request.
    • redirect_uri is the URL that you want the result of the authorization request to be sent to. This must match your client's registered URI.
    • code_challenge is the code_challenge you generated in the first step.
    • code_challenge_method must be S256.

    On success the user will be redirected to your redirect_uri with a code and the state as query parameters.
    On failure the user will also be redirected to your redirect_uri with details according to Section 4.1.2.1.
  3. Check that the state parameter matches one that you have generated. This helps ensure that the request comes from the correct instance of your application.
  4. Exchange the code for an access token using your application's credentials.
    Send a POST request to /oauth/token like in the following example:
    POST https://www.pathofexile.com/oauth/token
    ...
    Content-Type: application/x-www-form-urlencoded
     client_id=example &client_secret=verysecret &grant_type=authorization_code &code=d25cc653854f1d4db9c0797a30a374c6 &redirect_uri=https://example.com &scope=account:profile &code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
    • client_id is your registered application's client id.
    • client_secret is your registered application's client secret, if it has one.
    • grant_type is always authorization_code.
    • code is the authorization code obtained previously.
    • scope is a space-separated list of requested scopes.
    • redirect_uri is the URL that you received the authorization code with.
    • code_verifier is the code_verifier you generated in the first step.

    Authorization codes only last for 30 seconds, so make sure to exchange them quickly!
    On success you will receive a response with an access and refresh token for the user:
    {
        "access_token": "486132c90fedb152360bc0e1aa54eea155768eb9",
        "expires_in": 2592000,
        "token_type": "bearer",
        "scope": "account:profile",
        "username": "Novynn",
        "sub": "c5b9c286-8d05-47af-be41-67ab10a8c53e",
        "refresh_token": "17abaa74e599192f7650a4b89b6e9dfef2ff68cd"
    }

Client Credentials Grant

This grant can be used by an application in order to access services unrelated to an individual account that are exposed as part of the Path of Exile API. Unlike other tokens these ones do not have a set expiration time. They can still be revoked manually via your application settings page.

Flow:

  1. Submit a request for a token using the client_credentials grant:
    Send a POST request to /oauth/token like in the following example:
    POST https://www.pathofexile.com/oauth/token
    ...
    Content-Type: application/x-www-form-urlencoded
     client_id=example &client_secret=verysecret &grant_type=client_credentials &scope=service:psapi
    On success you will receive a response with an access token:
    {
        "access_token": "cded8a4638ae9bc5fe6cd897890e25e41f0f4e21",
        "expires_in": null,
        "token_type": "bearer",
        "username": "Novynn",
        "sub": "c5b9c286-8d05-47af-be41-67ab10a8c53e",
        "scope": "service:psapi"
    }
    Please note: tokens generated via the Client Credentials method have their identity set to the registered owner of the application. This means that tokens with appropriate scopes will have access your account details. It is extremely important that you keep your client credentials a secret. The owning account will also be used for rate-limiting endpoints where appropriate.

Refresh Token Grant

If your application has access to the refresh token grant type then you will receive an additional refresh_token property at the final step of the authorization code grant. This token lasts for 90 days and can be exchanged to generate a new access token without requesting the user's consent again.

Flow:

  1. Submit a request for a new access token using the refresh_token grant:
    Send a POST request to /oauth/token like in the following example:
    POST https://www.pathofexile.com/oauth/token
    ...
    Content-Type: application/x-www-form-urlencoded
     client_id=example &client_secret=verysecret &grant_type=refresh_token &refresh_token=17abaa74e599192f7650a4b89b6e9dfef2ff68cd
    On success you will receive a response with an access token and a new refresh token:
    {
        "access_token": "41bcefbc2f0d6ea0fa1cce10c435310d3c475e5b",
        "expires_in": 2592000,
        "token_type": "bearer",
        "scope": "account:profile"
        "username": "Novynn",
        "sub": "c5b9c286-8d05-47af-be41-67ab10a8c53e",
        "refresh_token": "4e9dbe97e038430bd943d35f8d5f8bef99699396"
    }
    Please note: The new refresh token that is returned will inherit the expiry time of the used token. You cannot extend the expiration time of your refresh token in any way. The used refresh token will also be immediately expired.

Authorizing a Request

Once you have an access token, all you need to do is include it in the Authorization header of a request:

Authorization: Bearer 486132c90fedb152360bc0e1aa54eea155768eb9

An HTTP 401 error will occur when the token has expired or has been revoked. You will need to generate a new one.

Similarly, an HTTP 403 error occurs when using a token that does not have the correct scope for the resource. You will need to generate a new one with the correct scopes set.

Managing Tokens

As access tokens allow access to a specific user's personal information, you must be careful in how you store them. You must not share access tokens with anyone but their owner. Since they do eventually expire it's fine to send them to the browser to store client-side in a Cookie or local storage as long as you do so using a secure method such as HTTPS.

Refresh tokens must always be stored in a secure manner server-side. If your application flow does not allow for this then refresh tokens can be turned off for your application to meet our requirements.