Project

Profile

Help

Using the Redmine REST API with OAuth2 at Planio » History » Sprint/Milestone 10

Jens Krämer, 08/22/2020 02:39 AM

1 9 Jens Krämer
# Using the Redmine REST API with OAuth 2 at Planio
2 1 Jens Krämer
3
As you might know, Planio comes with a powerful [REST API](https://plan.io/api)
4 9 Jens Krämer
which covers almost all aspects of Planio.
5 1 Jens Krämer
6 9 Jens Krämer
This guide will show you how to use OAuth 2 for authorizing access to this API.
7
8 1 Jens Krämer
{{>toc}}
9 9 Jens Krämer
10
 If you were working with the Redmine API before, you know that in order to use it, you had to generate an API key and
11
use that to make authorized API calls.
12 7 Jan Schulz-Hofen
13 1 Jens Krämer
This approach, while relatively easy to work with, has a few drawbacks:
14
15
- Each API key is tied to a single user account, meaning that your application
16
  will always act as this user when interacting with Planio.
17
- There is no way to restrict what an application can do - an API key always
18
  grants it's user the same set of permissions that the user it belongs to has.
19
20 10 Jens Krämer
**OAuth 2** defines a mechanism to restrict applications to a certain
21 1 Jens Krämer
*scope*. Further, users need to explicitly grant access to an application
22
before it may act on their behalf. When doing so, they will be informed about
23
the scope, that is, what data the application is going to have access to. In
24
the same way, a user may later decide to revert this decision and revoke access
25
for an application at any time.
26
27
Let's look a minimal example for you to try out.
28
29 8 Jan Schulz-Hofen
## Create an OAuth Application in your Planio Account
30 1 Jens Krämer
31
In order to use OAuth with Planio, you have to create an **Application** first.
32
This will generate a unique identifier for your API client, as well as a
33
secret. Both will be used to authenticate your application when it's
34
communicating with Planio.
35
36
Go to *Your Avatar* → **Administration** → **Applications** and click **New
37
Application**.
38
39 3 Jan Schulz-Hofen
{{figure(Creating a new OAuth application)
40 1 Jens Krämer
![Creating a new OAuth application](new_application%402x.png)
41 3 Jan Schulz-Hofen
}}
42 1 Jens Krämer
43
You may enter any descriptive **Name** for your application. This will be shown later to users when they are about to authorize your app.
44
45
The **Redirect URI** is the location where Planio will redirect a user's
46
browser to after they granted access to your application. The redirect will
47
carry a `code` query parameter which holds an authorization code that's needed
48
to retrieve the actuall access token later.
49
50
For now, enter `urn:ietf:wg:oauth:2.0:oob` as the **Redirect URI**. This
51
special value tells Planio that this application is not reachable over the
52
web. Instead, the authorization code will be simply displayed to the user for
53
manual transfer to the client application requesting access.
54
55
Below, in the **Scopes** section, you decide what your application will be
56
allowed to do. Don't be too generous here, and restrict the set of granted
57
permissions to the minimum necessary. For now, just select the
58
**Add issues** permission and hit **Save** below.
59
60
You will be redirected to a page that lists the details you just entered, along
61
with the application's **Application Id** and **Secret**.
62
63 8 Jan Schulz-Hofen
## Build the OAuth 2 client
64 1 Jens Krämer
65
We'll be using the [Ruby language](https://www.ruby-lang.org/en/) and the [OAuth2 Gem](https://rubygems.org/gems/oauth2) for this.
66
67
Of the various *OAuth Flows* that exist, Planio currently supports the most commonly used *Authorization Code* flow. Please refer to [the OAuth 2 spec](http://tools.ietf.org/html/rfc6749#section-4.1) for more technical details. Any applications you create are considered *confidential* in the sense of the spec, which means that the application secret may not be disclosed. If you require support for a *public* application (for example a mobile app or an application running exclusively in the browser), please contact us.
68
69 8 Jan Schulz-Hofen
### Set up the client
70 1 Jens Krämer
71
~~~ruby
72
require 'oauth2'
73
74
client_id     = '...' # your application id
75
client_secret = '...' # your application's secret
76
redirect_uri  = '...' # your application's redirect uri
77
site          = "https://your-domain.plan.io/" # your planio account's URL
78
79
client = OAuth2::Client.new(client_id, client_secret, site: site)
80
~~~
81
82
83 8 Jan Schulz-Hofen
### Authorize the Application
84 1 Jens Krämer
85
If you were building a real application, you would now send your user to some
86
URL where they are prompted to grant access. Usually you don't have to
87
construct these URLs yourself, but your OAuth 2 client library will do it for
88
you:
89
90
~~~ruby
91
client.auth_code.authorize_url(redirect_uri: redirect_uri, scope: 'add_issues')
92
# => https://your-domain.plan.io/oauth/authorize?response_type=code&client_id=...&redirect_uri=...
93
~~~
94
95
As `scope`, list all permissions you are planning to use. You cannot request
96
any permissions that have not been selected when the application was registered in Planio, but
97
you can choose to select less. Here, we only request the `add_issues` permission in order to be able to add issues.
98
99
Open this URL in your browser and you will be prompted for authorization,
100
listing the permissions you are applying for. 
101
102 4 Jan Schulz-Hofen
{{figure(Authorizing an OAuth 2 Application)
103 1 Jens Krämer
![Authorizing an OAuth 2 Application](authorize_app%402x.png)
104 4 Jan Schulz-Hofen
}}
105 1 Jens Krämer
106
Click **Authorize**, and take
107
note of the **Authorization code**. If you had entered a real **Redirect URI**
108
earlier, you would have been redirected to that URI now, with the authorization
109
code as query parameter.
110
111
112
113 8 Jan Schulz-Hofen
### Retrieve an Access Token
114 1 Jens Krämer
115
With the authorization code you can now request an access token from your
116
Planio account like this:
117
118
~~~ruby
119
code = '...' # the authorization code from above
120
token = client.auth_code.get_token(code, redirect_uri: redirect_uri)
121
# => <#OAuth2::AccessToken ...>
122
~~~
123
124
If at this point you get an error, it is most likely that the code, which is
125
only valid for a short time, already has expired.
126
127 8 Jan Schulz-Hofen
### Use the Access Token for API requests
128 1 Jens Krämer
129
If everything worked out, you may now use the token to do requests against
130
Planio's REST API.
131
132
~~~ruby
133
JSON.parse token.get('/users/current.json').body
134
~~~
135
136
This will give you some basic information about the user you are acting as. Of
137
course at this point you can stop using the OAuth 2 client and use any other
138
HTTP client to query Planio's API. Let's try with
139
[RestClient](https://github.com/rest-client/rest-client):
140
141
~~~ruby
142
# get the actual token string from the oauth lib
143
token_value = token.token
144
# compile the issue data
145
payload = { issue: { subject: "Hello world" } }
146
# specify the token in the Authorization HTTP header
147
headers = { Authorization: "Bearer #{token_value}"}
148
RestClient.post "https://your-domain.plan.io/projects/some-project/issues.json", payload, headers
149
# => <RestClient::Response 201 "{\"issue\":{\"...">
150
~~~
151
152
And that's it! You successfully created an issue with authorization obtained via OAuth 2.
153
154 8 Jan Schulz-Hofen
## A word on security
155 1 Jens Krämer
156
As the developer of an OAuth 2 client application it is your responsibility to keep the application secret as well as any auth and refresh tokens you obtain safe - any unintended disclosure may lead to unauthorized access to your users' data.
157
158 8 Jan Schulz-Hofen
## Manage your Authorized Applications
159 1 Jens Krämer
160
Click on *Your Avatar* → **My Account** → **Authorized Applications** in order
161
to see the list of applications that currently have access to your account.
162
163 5 Jan Schulz-Hofen
{{figure(List of authorized apps)
164 6 Jan Schulz-Hofen
![List of authorized apps](authorized_apps%402x.png)
165 5 Jan Schulz-Hofen
}}
166 1 Jens Krämer
167
Clicking **Revoke** will invalidate any access or refresh token that the application might still possess and remove it from the list.