Getting OAuth Access Tokens
To access gw2.me APIs to get info about the user or generate subtokens to access the Guild Wars 2 API you will need an access token. To get an access token the user needs to authorize your application first.
User Authorization
The first step is to get the user to authorize your application's access. Navigate the user to https://gw2.me/oauth2/authorize
. If your application is a website, you can for example use a hyperlink or a redirect. Native and mobile applications should open the default browser. Don't use iframes or embedded browsers.
Parameter | Type | Description |
---|---|---|
response_type | "code" | Must be code for authorization code grant. Other grants are not supported at the moment. |
redirect_uri | URL | The URL the user will be redirected back to after authorization. Must be an exact URL configured in your application settings. |
client_id | String | The client_id of your application. |
scope | String | List of scopes separated by spaces. |
include_granted_scopes (optional) | "true" | If this parameter is true , all previously authorized scopes will be included. This can be used for incremental authorization. |
prompt (optional) | "none" | "consent" |
|
state (optional) | String | Recommended string to improve security by preventing Cross-Site Request Forgery (CSRF) attacks. If the state returned to your redirect url does not match the state you provided in the request, the response should be ignored. The state string should be randomly generated and unique for each OAuth request. |
code_challenge (optional) | String | PKCE challenge. Required for public applications. |
code_challenge_method (optional) | "S256" | PKCE challenge method. Only SHA-256 is supported. |
verified_accounts_only (optional) | "true" | Only allow the user to select verified accounts. This requires the accounts.verified scope. |
An example request could look like this (URL formatted for better readability)
https://gw2.me/oauth2/authorize
?client_id=1554a6a3-8b8e-4ba7-9c5f-80576d081e10
&response_type=code
&redirect_uri=http%3A%2F%2Fexample.com%2Fcallback
&scope=identify+email+gw2%3Aaccount
&state=SaOfpb7Ny9mbV6EPCUDcnQ
&code_challenge=oFtTjTxdlTh9Tdwe8Rpbly8Qy8AL5rfKc9aueH_PmZM
&code_challenge_method=S256
If the user is not logged in to gw2.me yet, they get asked to login first. The user is then presented with a authorization page that shows your applications name, icon and all required scopes. If you requested any scopes for the Guild Wars 2 API, the user has to select at least one Guild Wars 2 account. The user can also add additional accounts on this screen.
After the user authorized your application, the user is redirected to the specified redirect_uri
.
If the authorization was successful, the url will contain the query parameter code
with an authorization code that needs to be exchanged for an access token in the next step.
https://example.com/callback
?state=SaOfpb7Ny9mbV6EPCUDcnQ
&iss=https%3A%2F%2Fgw2.me
&code=ciA-F7NVbINw1dcEVeYdww
If the authorization was not successful, the url will contain the error
and error_description
query parameters detailing the reason.
https://example.com/callback
?state=SaOfpb7Ny9mbV6EPCUDcnQ
&iss=https%3A%2F%2Fgw2.me
&error=access_denied
&error_description=user+canceled+authorization
The url for both the success and error response will always contain iss
and (if passed to the authorization request) state
, both of which should be verified. See Issuer Identification for more details on the iss
parameter.
Access Token
Next you will have to exchange the authorization code obtained in the first step for an access token (and refresh token).
You will have to make a POST request with Content-Type: application/x-www-form-urlencoded
to https://gw2.me/api/token
with the following parameters included in the body.
Parameter | Type | Description |
---|---|---|
grant_type | "authorization_code" | Should be authorization_code to exchange your authorization code for an access token. |
code | String | The authorization code received as callback from the authorization request. |
client_id | String | The client_id of your application. |
client_secret (optional) | String | The client_secret of your application. Only required for your confidential applications. |
redirect_uri | String | This must be the same redirect_uri as used in the authorization request. |
code_verifier (optional) | String | PKCE challenge verifier used to calculate code_challenge . |
Confidential applications have to authenticate themselves using their client secret. The client secret can either be passed using "Basic" HTTP Authentication (also called client_secret_basic
in the context of OAuth2), using the client_id
as username and the client_secret
as password, or by using client_secret_post
auth, passing the client_secret
as body parameter as part of the token response.
If the request is successful, the response will contain the access token used to access any other API endpoints.
{
"access_token": "xl1eSPfCpUNdQiIPe4TAag",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"token_type": "Bearer",
"expires_in": 604800,
"refresh_token": "mcn6FMwoiufzqcBDVwzOnz_NvGn-1ezzRKIm7vN_bsk",
"scope": "identify accounts gw2:account"
}
Next Steps
- Refresh Tokens when they expire.
- Generate a Guild Wars 2 Subtoken to access the Guild Wars 2 API.
- Check the API Reference for a list of all available APIs.
Incremental Authorization
It is best practice to only request access to scopes at the time you need them. Users are more likely to authorize your app if you require fewer permissions and the user knows what the different permissions are used for. You can request additional scopes later by navigating the user to the authorization page again. If you include the include_granted_scopes
query parameter when requesting user authorization, the access token will include all requested scopes in addition to all previously granted scopes.
For example you could just request the identity
scope at log in, and then later request additional permissions once the user starts a specific workflow in your app. If the user logs in again later, the granted scopes would usually not include the scopes required by the advanced workflow. But if the login request contains include_granted_scopes
, the access token generated by the login will already contain those extra scopes, because they were granted before.
Proof Key for Code Exchange (PKCE)
Proof Key for Code Exchange (PKCE) is a method to prevent code interception attacks. PKCE is required for public applications, and recommended for confidential applications. The method is described in the RFC 7636 - Proof Key for Code Exchange by OAuth Public Clients.
- First your application has to generate a high-entropy cryptographic random string called
code_verifier
. - You then have to hash the
code_verifier
using SHA-256. - When you request authorization, you pass the generated hash as
code_challenge
and setcode_challenge_method
toS256
. - After authorization, you now add the
code_verifier
to the access token request. - The server verifies the the
code_verifier
by comparing its hash with the earlier providedcode_challenge
. Only if it matches the server responds with an access token.
Issuer Identification
The authorization response contains the iss
parameter. This parameter is part of RFC 9207 - OAuth 2.0 Authorization Server Issuer Identification and contains the issuer identifier, which is always https://gw2.me
for gw2.me.
All clients should verify that this parameter exactly matches to prevent mix-up attacks.