oauth2.md 7.77 KB
Newer Older
1
# GitLab as an OAuth2 provider
Valery Sizov's avatar
Valery Sizov committed
2

3 4
This document covers using the [OAuth2](https://oauth.net/2/) protocol to allow
other services to access GitLab resources on user's behalf.
Valery Sizov's avatar
Valery Sizov committed
5

6 7 8 9
If you want GitLab to be an OAuth authentication service provider to sign into
other services, see the [OAuth2 provider](../integration/oauth_provider.md)
documentation. This functionality is based on the
[doorkeeper Ruby gem](https://github.com/doorkeeper-gem/doorkeeper).
10

11
## Supported OAuth2 flows
Valery Sizov's avatar
Valery Sizov committed
12

13
GitLab currently supports the following authorization flows:
Valery Sizov's avatar
Valery Sizov committed
14

15 16 17 18 19 20
- **Web application flow:** Most secure and common type of flow, designed for
  applications with secure server-side.
- **Implicit grant flow:** This flow is designed for user-agent only apps (e.g., single
  page web application running on GitLab Pages).
- **Resource owner password credentials flow:** To be used **only** for securely
  hosted, first-party services.
Valery Sizov's avatar
Valery Sizov committed
21

22 23
Refer to the [OAuth RFC](https://tools.ietf.org/html/rfc6749) to find out
how all those flows work and pick the right one for your use case.
24

25 26 27 28 29
Both **web application** and **implicit grant** flows require `application` to be
registered first via the `/profile/applications` page in your user's account.
During registration, by enabling proper scopes, you can limit the range of
resources which the `application` can access. Upon creation, you'll obtain the
`application` credentials: _Application ID_ and _Client Secret_ - **keep them secure**.
Valery Sizov's avatar
Valery Sizov committed
30

31 32 33 34 35 36
CAUTION: **Important:**
OAuth specification advises sending the `state` parameter with each request to
`/oauth/authorize`. We highly recommended sending a unique value with each request
and validate it against the one in the redirect request. This is important in
order to prevent [CSRF attacks](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)).
The `state` parameter really should have been a requirement in the standard!
37

38 39
In the following sections you will find detailed instructions on how to obtain
authorization with each flow.
Valery Sizov's avatar
Valery Sizov committed
40

41
### Web application flow
Valery Sizov's avatar
Valery Sizov committed
42

43 44 45
NOTE: **Note:**
Check the [RFC spec](https://tools.ietf.org/html/rfc6749#section-4.1) for a
detailed flow description.
46

47
The web application flow is:
Valery Sizov's avatar
Valery Sizov committed
48

49 50
1. Request authorization code. To do that, you should redirect the user to the
   `/oauth/authorize` endpoint with the following GET parameters:
Valery Sizov's avatar
Valery Sizov committed
51

52 53 54
   ```
   https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=code&state=YOUR_UNIQUE_STATE_HASH
   ```
55

56 57 58
   This will ask the user to approve the applications access to their account and
   then redirect back to the `REDIRECT_URI` you provided. The redirect will
   include the GET `code` parameter, for example:
59

60 61 62
   ```
   http://myapp.com/oauth/redirect?code=1234567890&state=YOUR_UNIQUE_STATE_HASH
   ```
63

64
   You should then use `code` to request an access token.
Valery Sizov's avatar
Valery Sizov committed
65

66 67 68
1. Once you have the authorization code you can request an `access_token` using the
   code. You can do that by using any HTTP client. In the following example,
   we are using Ruby's `rest-client`:
69

70 71 72 73
   ```ruby
   parameters = 'client_id=APP_ID&client_secret=APP_SECRET&code=RETURNED_CODE&grant_type=authorization_code&redirect_uri=REDIRECT_URI'
   RestClient.post 'http://gitlab.example.com/oauth/token', parameters
   ```
Valery Sizov's avatar
Valery Sizov committed
74

75
   Example response:
Valery Sizov's avatar
Valery Sizov committed
76

77 78 79 80 81 82 83 84
   ```json
   {
    "access_token": "de6780bc506a0446309bd9362820ba8aed28aa506c71eedbe1c5c4f9dd350e54",
    "token_type": "bearer",
    "expires_in": 7200,
    "refresh_token": "8257e65c97202ed1726cf9571600918f3bffb2544b26e00a61df9897668c33a1"
   }
   ```
Valery Sizov's avatar
Valery Sizov committed
85

86 87 88
NOTE: **Note:**
The `redirect_uri` must match the `redirect_uri` used in the original
authorization request.
Valery Sizov's avatar
Valery Sizov committed
89 90 91

You can now make requests to the API with the access token returned.

92
### Implicit grant flow
Valery Sizov's avatar
Valery Sizov committed
93

94 95 96
NOTE: **Note:**
Check the [RFC spec](https://tools.ietf.org/html/rfc6749#section-4.2) for a
detailed flow description.
97

98 99 100 101
CAUTION: **Important:**
Avoid using this flow for applications that store data outside of the GitLab
instance. If you do, make sure to verify `application id` associated with the
access token before granting access to the data
102
(see [/oauth/token/info](https://github.com/doorkeeper-gem/doorkeeper/wiki/API-endpoint-descriptions-and-examples#get----oauthtokeninfo)).
103

104 105 106 107
Unlike the web flow, the client receives an `access token` immediately as a
result of the authorization request. The flow does not use the client secret
or the authorization code because all of the application code and storage is
easily accessible, therefore secrets can leak easily.
108

109 110
To request the access token, you should redirect the user to the
`/oauth/authorize` endpoint using `token` response type:
Valery Sizov's avatar
Valery Sizov committed
111 112

```
113
https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=token&state=YOUR_UNIQUE_STATE_HASH
Valery Sizov's avatar
Valery Sizov committed
114 115
```

116 117 118 119
This will ask the user to approve the application's access to their account and
then redirect them back to the `REDIRECT_URI` you provided. The redirect
will include a fragment with `access_token` as well as token details in GET
parameters, for example:
Valery Sizov's avatar
Valery Sizov committed
120 121

```
122
http://myapp.com/oauth/redirect#access_token=ABCDExyz123&state=YOUR_UNIQUE_STATE_HASH&token_type=bearer&expires_in=3600
Valery Sizov's avatar
Valery Sizov committed
123 124
```

125
### Resource owner password credentials flow
Valery Sizov's avatar
Valery Sizov committed
126

127 128 129
NOTE: **Note:**
Check the [RFC spec](https://tools.ietf.org/html/rfc6749#section-4.3) for a
detailed flow description.
130

131 132 133 134 135
NOTE: **Note:**
The Resource Owner Password Credentials is disabled for users with [two-factor
authentication](../user/profile/account/two_factor_authentication.md) turned on.
These users can access the API using [personal access tokens](../user/profile/personal_access_tokens.md)
instead.
136

137 138
In this flow, a token is requested in exchange for the resource owner credentials
(username and password).
Valery Sizov's avatar
Valery Sizov committed
139

140
The credentials should only be used when:
141

142 143 144 145
- There is a high degree of trust between the resource owner and the client. For
  example, the client is part of the device operating system or a highly
  privileged application.
- Other authorization grant types are not available (such as an authorization code).
146

147 148 149 150 151
CAUTION: **Important:**
Never store the user's credentials and only use this grant type when your client
is deployed to a trusted environment, in 99% of cases
[personal access tokens](../user/profile/personal_access_tokens.md) are a better
choice.
152

153 154 155 156 157
Even though this grant type requires direct client access to the resource owner
credentials, the resource owner credentials are used for a single request and
are exchanged for an access token. This grant type can eliminate the need for
the client to store the resource owner credentials for future use, by exchanging
the credentials with a long-lived access token or refresh token.
Valery Sizov's avatar
Valery Sizov committed
158

159 160 161 162
To request an access token, you must make a POST request to `/oauth/token` with
the following parameters:

```json
Valery Sizov's avatar
Valery Sizov committed
163 164 165
{
  "grant_type"    : "password",
  "username"      : "user@example.com",
166
  "password"      : "secret"
Valery Sizov's avatar
Valery Sizov committed
167 168 169
}
```

170 171 172 173 174 175 176
Example cURL request:

```sh
echo 'grant_type=password&username=<your_username>&password=<your_password>' > auth.txt
curl --data "@auth.txt" --request POST https://gitlab.example.com/oauth/token
```

Valery Sizov's avatar
Valery Sizov committed
177 178 179 180 181 182 183 184 185 186
Then, you'll receive the access token back in the response:

```
{
  "access_token": "1f0af717251950dbd4d73154fdf0a474a5c5119adad999683f5b450c460726aa",
  "token_type": "bearer",
  "expires_in": 7200
}
```

187
For testing, you can use the `oauth2` Ruby gem:
Valery Sizov's avatar
Valery Sizov committed
188 189 190

```
client = OAuth2::Client.new('the_client_id', 'the_client_secret', :site => "http://example.com")
191
access_token = client.password.get_token('user@example.com', 'secret')
Valery Sizov's avatar
Valery Sizov committed
192
puts access_token.token
193
```
194

195
##  Access GitLab API with `access token`
196

197 198 199
The `access token` allows you to make requests to the API on behalf of a user.
You can pass the token either as GET parameter:

200 201 202 203 204 205 206 207 208
```
GET https://gitlab.example.com/api/v4/user?access_token=OAUTH-TOKEN
```

or you can put the token to the Authorization header:

```
curl --header "Authorization: Bearer OAUTH-TOKEN" https://gitlab.example.com/api/v4/user
```