Difference between revisions of "Development/OAuth2"

From MusicBrainz Wiki
(Replace reference to non-existent /ws/2/user with /oauth2/userinfo)
 
(19 intermediate revisions by 4 users not shown)
Line 1: Line 1:
OAuth2 is a protocol that lets external applications request authentication of the user and authorization to perform actions using the [[Development/XML_Web_Service/Version_2|web service]] on their behalf without getting their password. It is an alternative to [http://en.wikipedia.org/wiki/Digest_access_authentication HTTP Digest Access Authentication] that MusicBrainz currently uses.
+
OAuth2 is a protocol that lets external applications request authentication of the user and authorization to perform actions using the [[Development/XML_Web_Service/Version_2|web service]] on their behalf without getting their password. It is an alternative to [[wikipedia:Digest_access_authentication|HTTP Digest Access Authentication]] that MusicBrainz currently uses.
  
 
== Basic steps ==
 
== Basic steps ==
Line 5: Line 5:
 
=== Registering an application ===
 
=== Registering an application ===
  
All developers need to [https://musicbrainz.org/account/applications register their application] before getting started. A registered OAuth application is assigned a unique Client I and Client Secret. The OAuth protocol recognizes two types of applications:
+
All developers need to [[mb:account/applications|register their application]] before getting started. A registered OAuth application is assigned a unique Client I and Client Secret. The OAuth protocol recognizes two types of applications:
  
 
# Confidential - Applications that can keep secrets. Typically web applications, running on a server.
 
# Confidential - Applications that can keep secrets. Typically web applications, running on a server.
Line 14: Line 14:
 
=== Obtaining access token ===
 
=== Obtaining access token ===
  
...
+
The general work-flow for obtaining an access token is the following:
 +
 
 +
# Redirect the user to the OAuth authorization page with the appropriate parameters. From a desktop application, you need to open a browser with the URL for the user.
 +
# After the user authorizes the request, you will receive an authorization code. The authorization code is either delivered to the configured redirect URL or the user copies it to the application manually if using the out-of-band (OOB) method.
 +
# Send a request exchange the authorization code for an access token and optionally a refresh token.
 +
 
 +
Details of the steps are explained below.
  
 
=== Using access token ===
 
=== Using access token ===
  
After an application has obtained an access token, it may use the token in the web service to get user details or submit data to MusicBrainz on the user's behalf. There are two types of access tokens:
+
After an application has obtained an access token, it may use the token in the web service to get user details or submit data to MusicBrainz on the user's behalf. MusicBrainz currently only supports Bearer tokens which are very easy to use, but can be only sent over HTTPS.
 
 
# Bearer - Very easy to use, but can be used only over HTTPS.
 
# MAC - Requires requests to be signed with a secret, but can be used over both HTTP and HTTPS.
 
  
 
=== Refreshing access token ===
 
=== Refreshing access token ===
Line 29: Line 32:
 
== Authorization ==
 
== Authorization ==
  
=== Scopes ===
+
=== Authorization request ===
 +
 
 +
The authorization sequence starts by redirecting the user to the authorization endpoint with a set of query string parameters describing the authorization request. The endpoint is located at <code><nowiki>https://musicbrainz.org/oauth2/authorize</nowiki></code> and is only accessible over HTTPS. HTTP connections are refused.
 +
 
 +
The following set of query string parameters is supported by the MusicBrainz authentication endpoint:
 +
 
 +
; <code>response_type</code>
 +
: Must be always set to <code>code</code>.
 +
; <code>client_id</code>
 +
: Client ID assigned to your application. You can find it on the website in your list of registered applications.
 +
; <code>redirect_uri</code>
 +
: URL where clients should be redirected after authorization. This must match exactly the URL you entered when registering your application. Desktop applications can use either <code>urn:ietf:wg:oauth:2.0:oob</code> or <code><nowiki>http://localhost</nowiki></code> with a custom port.
 +
; <code>scope</code>
 +
: Space delimited list of scopes the application requests. See below for a list of all available scopes.
 +
; <code>state</code> (optional)
 +
: Any string the application wants passed back after authorization. For example, this can be a CSRF token from your application. This parameter is optional, but strongly recommended.
 +
 
 +
There are two extra parameters applicable only to web server applications:
 +
 
 +
; <code>access_type</code> (optional)
 +
: Indicates if your application needs to access the API when the user is not present at the browser. This parameter defaults to <code>online</code>. If your application needs to refresh access tokens when the user is not present at the browser, then use <code>offline</code>. This will result in your application obtaining a refresh token the first time your application exchanges an authorization code for a user.
 +
; <code>approval_prompt</code> (optional)
 +
: Indicates if the user should be re-prompted for consent. The default is <code>auto</code>, so a given user should only see the consent page for a given set of scopes the first time through the sequence. If the value is <code>force</code>, then the user sees a consent page even if they have previously given consent to your application for a given set of scopes.
 +
 
 +
For example, a complete authorization request from a web application requesting permissions to read the user's private tags and ratings would look like this:
 +
 
 +
<nowiki>https://musicbrainz.org/oauth2/authorize?
 +
  response_type=code&
 +
  client_id=uTuPnUfMRQPx8HBnHf22eg&
 +
  redirect_uri=http%3A%2F%2Fwww.example.com.com%2Fauth2callback&
 +
  scope=tag%20rating&
 +
  state=1351449443</nowiki>
 +
 
 +
The response to the authorization request will be sent to the URL indicated in the <code>redirect_uri</code> parameter. The authorization endpoint will redirect the user to this URL with a set of specific query string parameters indicating the result. If the user does not approve the request or there is a problem with the request, it will return an error describing the problem. Otherwise it will return an authorization code that can be exchanged for an access token by the token endpoint.
 +
 
 +
In case of an error, the response will look like this:
 +
 
 +
<nowiki>http://www.example.com/oauth2callback?state=1351449443&error=access_denied</nowiki>
 +
 
 +
Possible error codes are <code>unsupported_response_type</code>, <code>invalid_scope</code> and <code>access_denied</code>. If there is a problem with the <code>client_id</code> or <code>redirect_uri</code> parameters, the authorization endpoint will ''not'' redirect back to your application and only inform the user about the problem.
 +
 
 +
A successful authorization response:
 +
 
 +
<nowiki>http://www.example.com/oauth2callback?state=1351449443&code=Nlaa7v15QHm9g8rUOmT3dQ</nowiki>
 +
 
 +
=== Exchanging authorization code for an access token ===
 +
 
 +
Once your application receives an authorization code, it can send a POST request the token endpoint located at <code><nowiki>https://musicbrainz.org/oauth2/token</nowiki></code>, to exchange the code for an access token. As before, this endpoint is only avilable over HTTPS and HTTP requests will be refused.
 +
 
 +
The requires parameters for exchanging the authorization code are:
 +
 
 +
;<code>grant_type</code>
 +
: Must be set to <code>authorization_code</code>.
 +
;<code>code</code>
 +
: Authorization code from the initial request.
 +
;<code>client_id</code>
 +
: Client ID assigned to your application.
 +
;<code>client_secret</code>
 +
: Client secret assigned to your application.
 +
;<code>redirect_uri</code>
 +
: Redirect URL registered with the application.
 +
;<code>token_type</code> (optional)
 +
: Indicates which kind of token do you want to get, which can be either <code>bearer</code> or <code>mac</code>. The default value is <code>bearer</code>.
 +
 
 +
An example of an authorization code exchange would look like this:
 +
 
 +
POST /oauth2/token HTTP/1.1
 +
Host: musicbrainz.org
 +
Content-Type: application/x-www-form-urlencoded
 +
 
 +
grant_type=authorization_code&
 +
code=Nlaa7v15QHm9g8rUOmT3dQ&
 +
client_id=uTuPnUfMRQPx8HBnHf22eg&
 +
client_secret=7Fjfp0ZBr1KtDRbnfVdmIw&
 +
redirect_uri=http%3A%2F%2Fwww.example.com.com%2Fauth2callback
 +
 
 +
In case the authorization code and the client credentials were all valid, the server would respond with a JSON document in this format:
 +
 
 +
{
 +
  "access_token":"8OC8as1VpATqkM79KfcdTw",
 +
  "expires_in":3600,
 +
  "token_type":"Bearer",
 +
  "refresh_token":"Td5-okcuJvqgXLuq_YMXHA"
 +
}
 +
 
 +
=== Refreshing an access token ===
 +
 
 +
If you have an installed application, or web application with offline access, you have received a refresh token during the authorization process. This token can be used to get a new access token without any user interaction. Access tokens have a limited life-time, but the refresh token stays valid until the user manually revokes it.
 +
 
 +
The required parameters for refreshing an access token are:
 +
 
 +
;<code>grant_type</code>
 +
: Must be set to <code>refresh_token</code>.
 +
;<code>refresh_token</code>
 +
: Refresh token received during the authorization process.
 +
;<code>client_id</code>
 +
: Client ID assigned to your application.
 +
;<code>client_secret</code>
 +
: Client secret assigned to your application.
 +
;<code>token_type</code> (optional)
 +
: Indicates which kind of token do you want to get, which can be either <code>bearer</code> or <code>mac</code>. The default value is <code>bearer</code>.
 +
 
 +
An example of an authorization code exchange would look like this:
 +
 
 +
POST /oauth2/token HTTP/1.1
 +
Host: musicbrainz.org
 +
Content-Type: application/x-www-form-urlencoded
 +
 
 +
grant_type=refresh_token&
 +
refresh_token=Td5-okcuJvqgXLuq_YMXHA&
 +
client_id=uTuPnUfMRQPx8HBnHf22eg&
 +
client_secret=7Fjfp0ZBr1KtDRbnfVdmIw
 +
 
 +
In case the refresh token and the client credentials were all valid, the server would respond with a JSON document in this format:
 +
 
 +
{
 +
  "access_token":"z9KbV1DsP3PEomRFVpDBzg",
 +
  "expires_in":3600,
 +
  "token_type":"Bearer",
 +
  "refresh_token":"Td5-okcuJvqgXLuq_YMXHA"
 +
}
 +
 
 +
== Scopes ==
  
 
Authorization requests have a limited scope. You should request only the scopes that your application necessarily needs. The following scopes are available in the MusicBrainz OAuth implementation:
 
Authorization requests have a limited scope. You should request only the scopes that your application necessarily needs. The following scopes are available in the MusicBrainz OAuth implementation:
  
; profile
+
; <code>profile</code>
 
: View the user's public profile information (username, age, country, homepage).
 
: View the user's public profile information (username, age, country, homepage).
; email
+
; <code>email</code>
 
: View the user's email.
 
: View the user's email.
; tag
+
; <code>tag</code>
 
: View and modify the user's private tags.
 
: View and modify the user's private tags.
; rating
+
; <code>rating</code>
 
: View and modify the user's private ratings.
 
: View and modify the user's private ratings.
; collection
+
; <code>collection</code>
 
: View and modify the user's private collections.
 
: View and modify the user's private collections.
; submit_puid
+
; <code>submit_isrc</code>
: Submit new PUIDs to the database.
 
; submit_isrc
 
 
: Submit new ISRCs to the database.
 
: Submit new ISRCs to the database.
; submit_barcode
+
; <code>submit_barcode</code>
 
: Submit barcodes to the database.
 
: Submit barcodes to the database.
  
 
== Access token usage ==
 
== Access token usage ==
 +
 +
The authorization endpoint can return two types of access tokens. The authentication process is different for each of them.
  
 
=== Bearer tokens ===
 
=== Bearer tokens ===
Line 58: Line 183:
 
The preferred method to use bearer tokens is via the <code>Authorization</code> header. An authenticated request would look like the following:
 
The preferred method to use bearer tokens is via the <code>Authorization</code> header. An authenticated request would look like the following:
  
   GET /ws/2/user?name=xxx HTTP/1.1
+
   GET /oauth2/userinfo HTTP/1.1
 
   Host: musicbrainz.org
 
   Host: musicbrainz.org
 
   Authorization: Bearer jr5xkCAg4hGcls9FXMVIuQ
 
   Authorization: Bearer jr5xkCAg4hGcls9FXMVIuQ
Line 64: Line 189:
 
If you can't use the <code>Authorization</code> header, there is an alternative in which you can pass the access token in the <code>access_token</code> query string parameter:
 
If you can't use the <code>Authorization</code> header, there is an alternative in which you can pass the access token in the <code>access_token</code> query string parameter:
  
   GET https://musicbrainz.org/ws/2/user?name=xxx&access_token=jr5xkCAg4hGcls9FXMVIuQ
+
   <nowiki>GET https://musicbrainz.org/oauth2/userinfo?access_token=jr5xkCAg4hGcls9FXMVIuQ</nowiki>
  
 
You can try it with the curl command line application:
 
You can try it with the curl command line application:
  
   curl -H 'Authorization: Bearer jr5xkCAg4hGcls9FXMVIuQ' https://musicbrainz.org/ws/2/user?name=xxx
+
   <nowiki>curl -H 'Authorization: Bearer jr5xkCAg4hGcls9FXMVIuQ' https://musicbrainz.org/oauth2/userinfo</nowiki>
  
 
Or the query string parameter version:
 
Or the query string parameter version:
  
   curl 'https://musicbrainz.org/ws/2/user?name=xxx&access_token=jr5xkCAg4hGcls9FXMVIuQ'
+
   <nowiki>curl 'https://musicbrainz.org/oauth2/userinfo?access_token=jr5xkCAg4hGcls9FXMVIuQ'</nowiki>
  
 
Bearer tokens are specified in [http://tools.ietf.org/html/rfc6750 RFC 6750].
 
Bearer tokens are specified in [http://tools.ietf.org/html/rfc6750 RFC 6750].
  
=== MAC tokens ===
+
[[Category:WikiDocs Page]]
 
 
''The specification for MAC token is not yet complete, so this authentication method might change as the specification develops. MusicBrainz implementation is based on revision 01 of the specification draft and only supports HMAC-SHA1 signatures.''
 
 
 
MAC tokens consist of a public access token and a secret key associated with the token. They require application developers to send signed requests and can be used over both HTTP and HTTPS, because the access token is not considered a secret alone.
 
 
 
First, the application needs to get the current timestamp and a short random string that should be unique for the timestamp called nonce. Let's assume we have timestamp <code>1336363200</code> and nonce <code>dj83hs9s</code>. We need to calculate a [http://en.wikipedia.org/wiki/Hash-based_message_authentication_code HMAC] signature of the request, which is done using a normalized request string.
 
 
 
  1336363200\n
 
  dj83hs9s\n
 
  GET\n
 
  /ws/2/user?name=xxx\n
 
  musicbrainz.org\n
 
  80\n
 
  \n
 
 
 
Using this string as a message and the secret key assigned from the token, we calculate a [http://en.wikipedia.org/wiki/Base64 base64] encoded signature using HMAC-SHA1, which in this example is <code>MY2RO3VylIdLgFXx8bIdyce/544=</code> if the secret key was <code>yi3qjrMf4hG9VVUxXMVIuQ</code>.
 
 
 
An authenticated request with access token <code>jr5xkCAg4hGcls9FXMVIuQ</code> would then look like the following:
 
 
 
  GET /ws/2/user?name=xxx HTTP/1.1
 
  Host: musicbrainz.org
 
  Authorization: MAC id="jr5xkCAg4hGcls9FXMVIuQ" ts="1336363200" nonce="dj83hs9s" mac="LGqwjo25phvhlgBr4b1NFE7EGmM="
 
 
 
If you want to use use this authentication method, please refer to the [http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-01 specification] for details or use an OAuth 2.0 client library that has it already implemenmted.
 

Latest revision as of 21:41, 24 January 2019

OAuth2 is a protocol that lets external applications request authentication of the user and authorization to perform actions using the web service on their behalf without getting their password. It is an alternative to HTTP Digest Access Authentication that MusicBrainz currently uses.

Basic steps

Registering an application

All developers need to register their application before getting started. A registered OAuth application is assigned a unique Client I and Client Secret. The OAuth protocol recognizes two types of applications:

  1. Confidential - Applications that can keep secrets. Typically web applications, running on a server.
  2. Public - Applications that have their code exposed to the public and therefore cannot keep secrets. There are typically installed desktop applications or web applications running in the browser.

Client Secret assigned to Confidential applications should not be shared. This does not apply to Public applications, in which case the assigned Client Secret is not treated as a secret and can be embedded in the application code.

Obtaining access token

The general work-flow for obtaining an access token is the following:

  1. Redirect the user to the OAuth authorization page with the appropriate parameters. From a desktop application, you need to open a browser with the URL for the user.
  2. After the user authorizes the request, you will receive an authorization code. The authorization code is either delivered to the configured redirect URL or the user copies it to the application manually if using the out-of-band (OOB) method.
  3. Send a request exchange the authorization code for an access token and optionally a refresh token.

Details of the steps are explained below.

Using access token

After an application has obtained an access token, it may use the token in the web service to get user details or submit data to MusicBrainz on the user's behalf. MusicBrainz currently only supports Bearer tokens which are very easy to use, but can be only sent over HTTPS.

Refreshing access token

Access tokens have a limited life-time. During the authorization process, application receives a refresh token, in addition to the first access token. This refresh token allows applications to obtain new access tokens.

Authorization

Authorization request

The authorization sequence starts by redirecting the user to the authorization endpoint with a set of query string parameters describing the authorization request. The endpoint is located at https://musicbrainz.org/oauth2/authorize and is only accessible over HTTPS. HTTP connections are refused.

The following set of query string parameters is supported by the MusicBrainz authentication endpoint:

response_type
Must be always set to code.
client_id
Client ID assigned to your application. You can find it on the website in your list of registered applications.
redirect_uri
URL where clients should be redirected after authorization. This must match exactly the URL you entered when registering your application. Desktop applications can use either urn:ietf:wg:oauth:2.0:oob or http://localhost with a custom port.
scope
Space delimited list of scopes the application requests. See below for a list of all available scopes.
state (optional)
Any string the application wants passed back after authorization. For example, this can be a CSRF token from your application. This parameter is optional, but strongly recommended.

There are two extra parameters applicable only to web server applications:

access_type (optional)
Indicates if your application needs to access the API when the user is not present at the browser. This parameter defaults to online. If your application needs to refresh access tokens when the user is not present at the browser, then use offline. This will result in your application obtaining a refresh token the first time your application exchanges an authorization code for a user.
approval_prompt (optional)
Indicates if the user should be re-prompted for consent. The default is auto, so a given user should only see the consent page for a given set of scopes the first time through the sequence. If the value is force, then the user sees a consent page even if they have previously given consent to your application for a given set of scopes.

For example, a complete authorization request from a web application requesting permissions to read the user's private tags and ratings would look like this:

https://musicbrainz.org/oauth2/authorize?
  response_type=code&
  client_id=uTuPnUfMRQPx8HBnHf22eg&
  redirect_uri=http%3A%2F%2Fwww.example.com.com%2Fauth2callback&
  scope=tag%20rating&
  state=1351449443

The response to the authorization request will be sent to the URL indicated in the redirect_uri parameter. The authorization endpoint will redirect the user to this URL with a set of specific query string parameters indicating the result. If the user does not approve the request or there is a problem with the request, it will return an error describing the problem. Otherwise it will return an authorization code that can be exchanged for an access token by the token endpoint.

In case of an error, the response will look like this:

http://www.example.com/oauth2callback?state=1351449443&error=access_denied

Possible error codes are unsupported_response_type, invalid_scope and access_denied. If there is a problem with the client_id or redirect_uri parameters, the authorization endpoint will not redirect back to your application and only inform the user about the problem.

A successful authorization response:

http://www.example.com/oauth2callback?state=1351449443&code=Nlaa7v15QHm9g8rUOmT3dQ

Exchanging authorization code for an access token

Once your application receives an authorization code, it can send a POST request the token endpoint located at https://musicbrainz.org/oauth2/token, to exchange the code for an access token. As before, this endpoint is only avilable over HTTPS and HTTP requests will be refused.

The requires parameters for exchanging the authorization code are:

grant_type
Must be set to authorization_code.
code
Authorization code from the initial request.
client_id
Client ID assigned to your application.
client_secret
Client secret assigned to your application.
redirect_uri
Redirect URL registered with the application.
token_type (optional)
Indicates which kind of token do you want to get, which can be either bearer or mac. The default value is bearer.

An example of an authorization code exchange would look like this:

POST /oauth2/token HTTP/1.1
Host: musicbrainz.org
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
code=Nlaa7v15QHm9g8rUOmT3dQ&
client_id=uTuPnUfMRQPx8HBnHf22eg&
client_secret=7Fjfp0ZBr1KtDRbnfVdmIw&
redirect_uri=http%3A%2F%2Fwww.example.com.com%2Fauth2callback

In case the authorization code and the client credentials were all valid, the server would respond with a JSON document in this format:

{
  "access_token":"8OC8as1VpATqkM79KfcdTw",
  "expires_in":3600,
  "token_type":"Bearer",
  "refresh_token":"Td5-okcuJvqgXLuq_YMXHA"
}

Refreshing an access token

If you have an installed application, or web application with offline access, you have received a refresh token during the authorization process. This token can be used to get a new access token without any user interaction. Access tokens have a limited life-time, but the refresh token stays valid until the user manually revokes it.

The required parameters for refreshing an access token are:

grant_type
Must be set to refresh_token.
refresh_token
Refresh token received during the authorization process.
client_id
Client ID assigned to your application.
client_secret
Client secret assigned to your application.
token_type (optional)
Indicates which kind of token do you want to get, which can be either bearer or mac. The default value is bearer.

An example of an authorization code exchange would look like this:

POST /oauth2/token HTTP/1.1
Host: musicbrainz.org
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token&
refresh_token=Td5-okcuJvqgXLuq_YMXHA&
client_id=uTuPnUfMRQPx8HBnHf22eg&
client_secret=7Fjfp0ZBr1KtDRbnfVdmIw

In case the refresh token and the client credentials were all valid, the server would respond with a JSON document in this format:

{
  "access_token":"z9KbV1DsP3PEomRFVpDBzg",
  "expires_in":3600,
  "token_type":"Bearer",
  "refresh_token":"Td5-okcuJvqgXLuq_YMXHA"
}

Scopes

Authorization requests have a limited scope. You should request only the scopes that your application necessarily needs. The following scopes are available in the MusicBrainz OAuth implementation:

profile
View the user's public profile information (username, age, country, homepage).
email
View the user's email.
tag
View and modify the user's private tags.
rating
View and modify the user's private ratings.
collection
View and modify the user's private collections.
submit_isrc
Submit new ISRCs to the database.
submit_barcode
Submit barcodes to the database.

Access token usage

The authorization endpoint can return two types of access tokens. The authentication process is different for each of them.

Bearer tokens

Bearer tokens are the default type of access tokens. They are very easy to use, consist only of one component, which you should treat as a password. For this reason, it is only possible to use them over HTTPS. If you try to send them over plain HTTP, they will be ignored.

The preferred method to use bearer tokens is via the Authorization header. An authenticated request would look like the following:

 GET /oauth2/userinfo HTTP/1.1
 Host: musicbrainz.org
 Authorization: Bearer jr5xkCAg4hGcls9FXMVIuQ

If you can't use the Authorization header, there is an alternative in which you can pass the access token in the access_token query string parameter:

 GET https://musicbrainz.org/oauth2/userinfo?access_token=jr5xkCAg4hGcls9FXMVIuQ

You can try it with the curl command line application:

 curl -H 'Authorization: Bearer jr5xkCAg4hGcls9FXMVIuQ' https://musicbrainz.org/oauth2/userinfo

Or the query string parameter version:

 curl 'https://musicbrainz.org/oauth2/userinfo?access_token=jr5xkCAg4hGcls9FXMVIuQ'

Bearer tokens are specified in RFC 6750.