-
Notifications
You must be signed in to change notification settings - Fork 1
Home
To be able to request a users authorization, you first have to create a client. To do this, login at GW2Auth and navigate inside the Account-Management to Clients and click the button Register a new Client.
Choose a name for your client (this name will be displayed to the users) and fill in the redirect uri.
For local testing purposes, use http://127.0.0.1
. localhost
is not allowed. If you want to see how an authorization would look like, you can use https://gw2auth.com/account/client/debug
Once you have filled in all required values, click Create Client. You will now see an overview of your newly created client.
Make sure to copy the Client-Secret on this page, since it can't be displayed afterwards. Never give your Client-Secret to anyone else.
GW2Auth uses OAuth2.0 to authorize clients. For most web frameworks, you'll find an existing implementation which takes care of all the details. However, the following guide will show you the basics of how it works.
All relevant OAuth2.0 URLs are present in https://gw2auth.com/.well-known/oauth-authorization-server Most importantly, the following:
Key | Description |
---|---|
authorization_endpoint | Users have to be redirected to this Endpoint to initiate an authorization |
token_endpoint | This Endpoint has to be used in your backend to retrieve tokens for either an initiated authorization or to retrieve new tokens using an Refresh Token |
jwks_uri | This Endpoint should be used in your backend to retrieve tokens for either an initiated authorization or to retrieve new tokens using an Refresh Token |
During the initial authorization, the user which should authorize your client is required to be active. They have to actively authorize your client by selecting the GW2-Accounts they want to give your client access to.
For each authorization request, you should generate a random state-parameter on your side. Keep this randomly generated value in some store (in-memory, database, whatever your like). Note that an authorization can technically not be ensured to be fulfilled (a user may simply close the browser for example). So keep in mind to you cleanup unfulfilled authorizations at some point.
Generally, this state-parameter should be a randomly generated string to recognize the initiated authorization once it comes back to you.
The following scopes are supported for all clients at GW2Auth:
Scope | Description |
---|---|
gw2:account | GW2-API "account" permission for all GW2-Accounts selected by the user |
gw2:builds | GW2-API "builds" permission ... |
gw2:characters | GW2-API "characters" permission ... |
gw2:guilds | GW2-API "guilds" permission ... |
gw2:inventories | GW2-API "inventories" permission ... |
gw2:progression | GW2-API "progression" permission ... |
gw2:pvp | GW2-API "pvp" permission ... |
gw2:tradingpost | GW2-API "tradingpost" permission ... |
gw2:unlocks | GW2-API "unlocks" permission ... |
gw2:wallet | GW2-API "wallet" permission ... |
gw2auth:verified | Adds an additional field "verified" for all GW2-Accounts selected by the user. This represents the users GW2-Account-Verification status at GW2Auth (more information below) |
Next, you should redirect the user to the authorization_endpoint using the following parameters passed in the query:
Query Parameter | Description | Example Value |
---|---|---|
response_type | Must be code
|
code |
client_id | The Client-ID of your Client | d5dba13c-42d7-4c78-b6ea-9bcb7407112b |
state | The state-parameter you generated on your side (see above) | ioasho889dasdknadjhiahdiohi1290asin |
scope | The list of scopes you want to request (see above), separated by space. Must not be empty. In any order. | gw2:account gw2auth:verified |
redirect_uri | The redirect URI you used when creating the client | https://gw2auth.com/account/client/debug |
name (Optional) | A display name for this Authorization. If not passed, the internal authorization ID will be shown instead. Only pass this if you can provide a meaningful name - for client-side applications this could be the name of the current machine for example. | DESKTOP-12345 |
The user will now be shown a dialog where they have to select all their GW2-Accounts which they want your client give access to.
Important note: Due to the nature of redirects (they're handled on the client side), a user may take the Location
-Header of your redirect, keep the state parameter but modify the scope
-Parameter. We will come back to this below.
Once the user either approved or declined the requested authorization, they will be redirected to the URI given in the initial request.
If the user declined the authorization (by clicking Cancel on the authorization page), the following Query Parameters will be present in the request:
Query Parameter | Description | Example Value |
---|---|---|
error | An OAuth2 Error-Code | access_denied |
error_description | A detailed description of the error | The user has denied your application access. |
If the user approved the authorization (by selecting at least one GW2-Account and clicking Authorize), the following Query Parameters will be present in the request:
Query Parameter | Description | Example Value |
---|---|---|
code | A short-lived one time code which can be used to retrieve the initial Refresh- and Access-Token | wGS4oW0Dm8hPxlY9EF3lhRBeXvBAoQu2iLgwONa2CaVqftHog0dPJ4zCOnFkFkVWQXZbLYH434iGuJFScNOvQgAlrw8ZsO6hquFxSG7y3HUpSWKrXl3IBF4-UOzatEP- |
state | The state-Parameter passed to the redirection in the step before | ioasho889dasdknadjhiahdiohi1290asin |
While processing the request above, your backend should use the passed code
-Parameter to retrieve the initial Refresh- and Access-Token.
To do this, perform a POST
-Request to the token_endpoint
mentioned above and pass the following Query-Parameters:
Query Parameter | Description | Example Value |
---|---|---|
grant_type | Must be authorization_code
|
authorization_code |
code | The code -Parameter given to the request you're currently processing (see above) |
wGS4oW0Dm8hPxlY9EF3lhRBeXvBAoQu2iLgwONa2CaVqftHog0dPJ4zCOnFkFkVWQXZbLYH434iGuJFScNOvQgAlrw8ZsO6hquFxSG7y3HUpSWKrXl3IBF4-UOzatEP- |
client_id | The Client-ID of your Client | d5dba13c-42d7-4c78-b6ea-9bcb7407112b |
client_secret | The Client-Secret of your Client (the one you copied right after creating your client) | Sx9skfRMXxIVfX7UWaktKP9od1pV7kLGDSBzdsvZIZ1xdApzrOHTfom6m8XNrpVa |
redirect_uri | The exact same redirect_uri that has been passed to the initial authorization request | https://gw2auth.com/account/client/debug |
A successful response will look like this:
{
"access_token": "" // Access-Token (JWT),
"refresh_token": "uVKRO-gElNXaAF_VNg-6u8jbmtlazLDNC3ljPiX92rCY3j59Oe6Lt3V2PnZJZEny6ZMUQ8FCZkjzLMfXrNgymvBLW4RYEpPSLb7QRX5QtPaGIhqsXKcufJrX3jR1bJBw",// the Refresh Token used to retrieve new Access Tokens (without user interaction)
"scope":"gw2auth:verified gw2:account",// the authorized scopes (see important note below)
"token_type": "Bearer",
"expires_in": 1799 // seconds until the Access-Token expires
}
Important note: As mentioned above, a user can potentionally manipulate the scopes passed in the initial redirect. Make sure to verify the scope
-Value here!
Persist the refresh_token
as you wish. This token can be used to request new Refresh- and Access-Tokens. Access-Tokens are valid for 30 minutes, while Refresh-Tokens are valid for 180 days. You always have to use the latest Refresh-Token.
Access-Tokens returned by GW2Auth are JWTs. The payload of these JWTs is a JSON containing the following values:
JSON-Key | JSON-Type | Description | Example Value |
---|---|---|---|
sub | string | A unique identifier for the GW2Auth-Account of the user. This value is not consistent across different clients. | 1f8f5637-8b14-4291-825a-76780440befd |
scope | list of strings | The list of authorized scopes | ["gw2:account", "gw2auth:verified"] |
iss | string | A URL of the issuer which created this Access-Token | https://gw2auth.com |
iat | number | UNIX-Timestamp (seconds): Timestamp at which this token was issued | 1635810481 |
exp | number | UNIX-Timestamp (seconds): Timestamp at which this token will expire | 1635812281 |
gw2:permissions | list of strings | The list of authorized GW2-API-Permissions | ["account"] |
gw2:tokens | object | A JSON-Object containing all subtokens (and some additional information) for all by the user authorized GW2-Accounts. Key: GW2-Account-ID ; Value: Token-Object (see below) | {"93DF54C6-78F7-E111-809D-78E7D1936EF0": {...}} |
JSON-Key | JSON-Type | Description | Example Value |
---|---|---|---|
name | string | The name of the GW2-Account, freely chosen by the user at GW2Auth | Felix.9127 (Main) |
token | string | The GW2-API-Subtoken, valid for exactly the same time as the Access-Token itself. Use this to perform GW2-API-Requests. Only present if error is not present. |
... |
error | string | An error description if, for any reason, no subtoken could be retrieved for this GW2-Account. Only present if token is not present. |
... |
verified | boolean | Only present if the scope gw2auth:verified was requested (and authorized) |
true |