changed
README.md
|
@@ -18,7 +18,7 @@ end
|
18
18
|
|
19
19
|
defp deps do
|
20
20
|
# Add the dependency
|
21
|
- [{:oauth2, "~> 1.0"}]
|
21
|
+ [{:oauth2, "~> 2.0"}]
|
22
22
|
end
|
23
23
|
```
|
24
24
|
|
|
@@ -48,7 +48,7 @@ for more details.
|
48
48
|
|
49
49
|
## Debug mode
|
50
50
|
|
51
|
- Some times its handy to see what's coming back from the response when getting
|
51
|
+ Sometimes it's handy to see what's coming back from the response when getting
|
52
52
|
a token. You can configure OAuth2 to output the response like so:
|
53
53
|
|
54
54
|
```elixir
|
|
@@ -170,7 +170,6 @@ defmodule GitHub do
|
170
170
|
|
171
171
|
def get_token(client, params, headers) do
|
172
172
|
client
|
173
|
- |> put_param(:client_secret, client.client_secret)
|
174
173
|
|> put_header("accept", "application/json")
|
175
174
|
|> OAuth2.Strategy.AuthCode.get_token(params, headers)
|
176
175
|
end
|
changed
hex_metadata.config
|
@@ -21,4 +21,4 @@
|
21
21
|
{<<"optional">>,false},
|
22
22
|
{<<"repository">>,<<"hexpm">>},
|
23
23
|
{<<"requirement">>,<<"~> 1.13">>}]]}.
|
24
|
- {<<"version">>,<<"1.0.1">>}.
|
24
|
+ {<<"version">>,<<"2.0.0">>}.
|
changed
lib/oauth2.ex
|
@@ -2,7 +2,7 @@ defmodule OAuth2 do
|
2
2
|
@moduledoc """
|
3
3
|
The OAuth2 specification
|
4
4
|
|
5
|
- https://tools.ietf.org/html/rfc6749
|
5
|
+ [RFC6749](https://tools.ietf.org/html/rfc6749)
|
6
6
|
|
7
7
|
The OAuth 2.0 authorization framework enables a third-party
|
8
8
|
application to obtain limited access to an HTTP service, either on
|
|
@@ -12,13 +12,13 @@ defmodule OAuth2 do
|
12
12
|
|
13
13
|
## API
|
14
14
|
|
15
|
- Current implemented strategies:
|
15
|
+ Currently implemented strategies:
|
16
16
|
|
17
17
|
- Authorization Code
|
18
18
|
- Password
|
19
19
|
- Client Credentials
|
20
20
|
|
21
|
- #### Authorization Code Flow (AuthCode Strategy)
|
21
|
+ ### Authorization Code Flow (AuthCode Strategy)
|
22
22
|
|
23
23
|
Initialize a client with your `client_id`, `client_secret`, and `site`.
|
changed
lib/oauth2/access_token.ex
|
@@ -14,19 +14,20 @@ defmodule OAuth2.AccessToken do
|
14
14
|
|
15
15
|
@standard ["access_token", "refresh_token", "expires_in", "token_type"]
|
16
16
|
|
17
|
- @type access_token :: binary
|
17
|
+ @type access_token :: binary
|
18
18
|
@type refresh_token :: binary | nil
|
19
|
- @type expires_at :: integer
|
20
|
- @type token_type :: binary
|
21
|
- @type other_params :: %{binary => binary}
|
22
|
- @type body :: binary | map
|
19
|
+ @type expires_at :: integer
|
20
|
+ @type token_type :: binary
|
21
|
+ @type other_params :: %{binary => binary}
|
22
|
+ @type body :: binary | map | list
|
23
23
|
|
24
24
|
@type t :: %__MODULE__{
|
25
|
- access_token: access_token,
|
26
|
- refresh_token: refresh_token,
|
27
|
- expires_at: expires_at,
|
28
|
- token_type: token_type,
|
29
|
- other_params: other_params}
|
25
|
+ access_token: access_token,
|
26
|
+ refresh_token: refresh_token,
|
27
|
+ expires_at: expires_at,
|
28
|
+ token_type: token_type,
|
29
|
+ other_params: other_params
|
30
|
+ }
|
30
31
|
|
31
32
|
defstruct access_token: "",
|
32
33
|
refresh_token: nil,
|
|
@@ -58,13 +59,13 @@ defmodule OAuth2.AccessToken do
|
58
59
|
def new(response) when is_map(response) do
|
59
60
|
{std, other} = Map.split(response, @standard)
|
60
61
|
|
61
|
- struct(AccessToken, [
|
62
|
- access_token: std["access_token"],
|
62
|
+ struct(AccessToken,
|
63
|
+ access_token: std["access_token"],
|
63
64
|
refresh_token: std["refresh_token"],
|
64
|
- expires_at: (std["expires_in"] || other["expires"]) |> expires_at,
|
65
|
- token_type: std["token_type"] |> normalize_token_type(),
|
66
|
- other_params: other
|
67
|
- ])
|
65
|
+ expires_at: (std["expires_in"] || other["expires"]) |> expires_at,
|
66
|
+ token_type: std["token_type"] |> normalize_token_type(),
|
67
|
+ other_params: other
|
68
|
+ )
|
68
69
|
end
|
69
70
|
|
70
71
|
@doc """
|
|
@@ -72,7 +73,7 @@ defmodule OAuth2.AccessToken do
|
72
73
|
|
73
74
|
Returns `true` unless `expires_at` is `nil`.
|
74
75
|
"""
|
75
|
- @spec expires?(AccessToken.t) :: boolean
|
76
|
+ @spec expires?(AccessToken.t()) :: boolean
|
76
77
|
def expires?(%AccessToken{expires_at: nil} = _token), do: false
|
77
78
|
def expires?(_), do: true
|
78
79
|
|
|
@@ -87,12 +88,14 @@ defmodule OAuth2.AccessToken do
|
87
88
|
Returns a unix timestamp based on now + expires_at (in seconds).
|
88
89
|
"""
|
89
90
|
def expires_at(nil), do: nil
|
91
|
+
|
90
92
|
def expires_at(val) when is_binary(val) do
|
91
93
|
val
|
92
|
- |> Integer.parse
|
94
|
+ |> Integer.parse()
|
93
95
|
|> elem(0)
|
94
96
|
|> expires_at
|
95
97
|
end
|
98
|
+
|
96
99
|
def expires_at(int), do: unix_now() + int
|
97
100
|
|
98
101
|
defp normalize_token_type(nil), do: "Bearer"
|
changed
lib/oauth2/client.ex
|
@@ -29,41 +29,41 @@ defmodule OAuth2.Client do
|
29
29
|
response = OAuth2.Client.post!(client, "/some/other/resources", %{foo: "bar"})
|
30
30
|
"""
|
31
31
|
|
32
|
- alias OAuth2.{AccessToken, Client, Error, Response, Request}
|
32
|
+ alias OAuth2.{AccessToken, Client, Error, Request, Response}
|
33
33
|
|
34
34
|
@type authorize_url :: binary
|
35
|
- @type body :: any
|
36
|
- @type client_id :: binary
|
35
|
+ @type body :: any
|
36
|
+ @type client_id :: binary
|
37
37
|
@type client_secret :: binary
|
38
|
- @type headers :: [{binary, binary}]
|
39
|
- @type param :: binary | %{binary => param} | [param]
|
40
|
- @type params :: %{binary => param} | Keyword.t
|
41
|
- @type redirect_uri :: binary
|
42
|
- @type ref :: reference | nil
|
43
|
- @type request_opts :: Keyword.t
|
44
|
- @type serializers :: %{binary => module}
|
45
|
- @type site :: binary
|
46
|
- @type strategy :: module
|
47
|
- @type token :: AccessToken.t | nil
|
48
|
- @type token_method :: :post | :get | atom
|
49
|
- @type token_url :: binary
|
38
|
+ @type headers :: [{binary, binary}]
|
39
|
+ @type param :: binary | %{binary => param} | [param]
|
40
|
+ @type params :: %{binary => param} | Keyword.t()
|
41
|
+ @type redirect_uri :: binary
|
42
|
+ @type ref :: reference | nil
|
43
|
+ @type request_opts :: Keyword.t()
|
44
|
+ @type serializers :: %{binary => module}
|
45
|
+ @type site :: binary
|
46
|
+ @type strategy :: module
|
47
|
+ @type token :: AccessToken.t() | nil
|
48
|
+ @type token_method :: :post | :get | atom
|
49
|
+ @type token_url :: binary
|
50
50
|
|
51
51
|
@type t :: %Client{
|
52
|
- authorize_url: authorize_url,
|
53
|
- client_id: client_id,
|
54
|
- client_secret: client_secret,
|
55
|
- headers: headers,
|
56
|
- params: params,
|
57
|
- redirect_uri: redirect_uri,
|
58
|
- ref: ref,
|
59
|
- request_opts: request_opts,
|
60
|
- serializers: serializers,
|
61
|
- site: site,
|
62
|
- strategy: strategy,
|
63
|
- token: token,
|
64
|
- token_method: token_method,
|
65
|
- token_url: token_url
|
66
|
- }
|
52
|
+ authorize_url: authorize_url,
|
53
|
+ client_id: client_id,
|
54
|
+ client_secret: client_secret,
|
55
|
+ headers: headers,
|
56
|
+ params: params,
|
57
|
+ redirect_uri: redirect_uri,
|
58
|
+ ref: ref,
|
59
|
+ request_opts: request_opts,
|
60
|
+ serializers: serializers,
|
61
|
+ site: site,
|
62
|
+ strategy: strategy,
|
63
|
+ token: token,
|
64
|
+ token_method: token_method,
|
65
|
+ token_url: token_url
|
66
|
+ }
|
67
67
|
|
68
68
|
defstruct authorize_url: "/oauth/authorize",
|
69
69
|
client_id: "",
|
|
@@ -126,7 +126,7 @@ defmodule OAuth2.Client do
|
126
126
|
|
127
127
|
[hackney documentation]: https://github.com/benoitc/hackney/blob/master/doc/hackney.md#request5
|
128
128
|
"""
|
129
|
- @spec new(t, Keyword.t) :: t
|
129
|
+ @spec new(t, Keyword.t()) :: t
|
130
130
|
def new(client \\ %Client{}, opts) do
|
131
131
|
{token, opts} = Keyword.pop(opts, :token)
|
132
132
|
{req_opts, opts} = Keyword.pop(opts, :request_opts, [])
|
|
@@ -149,7 +149,7 @@ defmodule OAuth2.Client do
|
149
149
|
The key can be a `string` or an `atom`. Atoms are automatically
|
150
150
|
convert to strings.
|
151
151
|
"""
|
152
|
- @spec put_param(t, String.t | atom, any) :: t
|
152
|
+ @spec put_param(t, String.t() | atom, any) :: t
|
153
153
|
def put_param(%Client{params: params} = client, key, value) do
|
154
154
|
%{client | params: Map.put(params, "#{key}", value)}
|
155
155
|
end
|
|
@@ -159,9 +159,11 @@ defmodule OAuth2.Client do
|
159
159
|
"""
|
160
160
|
@spec merge_params(t, params) :: t
|
161
161
|
def merge_params(client, params) do
|
162
|
- params = Enum.reduce(params, %{}, fn {k,v}, acc ->
|
163
|
- Map.put(acc, "#{k}", v)
|
164
|
- end)
|
162
|
+ params =
|
163
|
+ Enum.reduce(params, %{}, fn {k, v}, acc ->
|
164
|
+ Map.put(acc, "#{k}", v)
|
165
|
+ end)
|
166
|
+
|
165
167
|
%{client | params: Map.merge(client.params, params)}
|
166
168
|
end
|
167
169
|
|
|
@@ -171,7 +173,7 @@ defmodule OAuth2.Client do
|
171
173
|
"""
|
172
174
|
@spec put_header(t, binary, binary) :: t
|
173
175
|
def put_header(%Client{headers: headers} = client, key, value)
|
174
|
- when is_binary(key) and is_binary(value) do
|
176
|
+ when is_binary(key) and is_binary(value) do
|
175
177
|
key = String.downcase(key)
|
176
178
|
%{client | headers: List.keystore(headers, key, 0, {key, value})}
|
177
179
|
end
|
|
@@ -181,7 +183,8 @@ defmodule OAuth2.Client do
|
181
183
|
"""
|
182
184
|
@spec put_headers(t, list) :: t
|
183
185
|
def put_headers(%Client{} = client, []), do: client
|
184
|
- def put_headers(%Client{} = client, [{k,v}|rest]) do
|
186
|
+
|
187
|
+ def put_headers(%Client{} = client, [{k, v} | rest]) do
|
185
188
|
client
|
186
189
|
|> put_header(k, v)
|
187
190
|
|> put_headers(rest)
|
|
@@ -219,7 +222,7 @@ defmodule OAuth2.Client do
|
219
222
|
"""
|
220
223
|
@spec put_serializer(t, binary, atom) :: t
|
221
224
|
def put_serializer(%Client{serializers: serializers} = client, mime, module)
|
222
|
- when is_binary(mime) and is_atom(module) do
|
225
|
+ when is_binary(mime) and is_atom(module) do
|
223
226
|
%Client{client | serializers: Map.put(serializers, mime, module)}
|
224
227
|
end
|
225
228
|
|
|
@@ -266,7 +269,8 @@ defmodule OAuth2.Client do
|
266
269
|
* `:proxy` - a proxy to be used for the request; it can be a regular url or a
|
267
270
|
`{host, proxy}` tuple
|
268
271
|
"""
|
269
|
- @spec get_token(t, params, headers, Keyword.t) :: {:ok, Client.t} | {:error, Response.t} | {:error, Error.t}
|
272
|
+ @spec get_token(t, params, headers, Keyword.t()) ::
|
273
|
+ {:ok, Client.t()} | {:error, Response.t()} | {:error, Error.t()}
|
270
274
|
def get_token(%{token_method: method} = client, params \\ [], headers \\ [], opts \\ []) do
|
271
275
|
{client, url} = token_url(client, params, headers)
|
272
276
|
|
|
@@ -274,6 +278,7 @@ defmodule OAuth2.Client do
|
274
278
|
{:ok, response} ->
|
275
279
|
token = AccessToken.new(response.body)
|
276
280
|
{:ok, %{client | headers: [], params: %{}, token: token}}
|
281
|
+
|
277
282
|
{:error, error} ->
|
278
283
|
{:error, error}
|
279
284
|
end
|
|
@@ -283,22 +288,26 @@ defmodule OAuth2.Client do
|
283
288
|
Same as `get_token/4` but raises `OAuth2.Error` if an error occurs during the
|
284
289
|
request.
|
285
290
|
"""
|
286
|
- @spec get_token!(t, params, headers, Keyword.t) :: Client.t | Error.t
|
291
|
+ @spec get_token!(t, params, headers, Keyword.t()) :: Client.t() | Error.t()
|
287
292
|
def get_token!(client, params \\ [], headers \\ [], opts \\ []) do
|
288
293
|
case get_token(client, params, headers, opts) do
|
289
294
|
{:ok, client} ->
|
290
295
|
client
|
296
|
+
|
291
297
|
{:error, %Response{status_code: code, headers: headers, body: body}} ->
|
292
|
- raise %Error{reason: """
|
293
|
- Server responded with status: #{code}
|
298
|
+ raise %Error{
|
299
|
+ reason: """
|
300
|
+ Server responded with status: #{code}
|
294
301
|
|
295
|
- Headers:
|
302
|
+ Headers:
|
296
303
|
|
297
|
- #{Enum.reduce(headers, "", fn {k, v}, acc -> acc <> "#{k}: #{v}\n" end)}
|
298
|
- Body:
|
304
|
+ #{Enum.reduce(headers, "", fn {k, v}, acc -> acc <> "#{k}: #{v}\n" end)}
|
305
|
+ Body:
|
306
|
+
|
307
|
+ #{inspect(body)}
|
308
|
+ """
|
309
|
+ }
|
299
310
|
|
300
|
- #{inspect body}
|
301
|
- """}
|
302
311
|
{:error, error} ->
|
303
312
|
raise error
|
304
313
|
end
|
|
@@ -307,12 +316,20 @@ defmodule OAuth2.Client do
|
307
316
|
@doc """
|
308
317
|
Refreshes an existing access token using a refresh token.
|
309
318
|
"""
|
310
|
- @spec refresh_token(t, params, headers, Keyword.t) :: {:ok, Client.t} | {:error, Response.t} | {:error, Error.t}
|
319
|
+ @spec refresh_token(t, params, headers, Keyword.t()) ::
|
320
|
+ {:ok, Client.t()} | {:error, Response.t()} | {:error, Error.t()}
|
311
321
|
def refresh_token(token, params \\ [], headers \\ [], opts \\ [])
|
322
|
+
|
312
323
|
def refresh_token(%Client{token: %{refresh_token: nil}}, _params, _headers, _opts) do
|
313
324
|
{:error, %Error{reason: "Refresh token not available."}}
|
314
325
|
end
|
315
|
- def refresh_token(%Client{token: %{refresh_token: refresh_token}} = client, params, headers, opts) do
|
326
|
+
|
327
|
+ def refresh_token(
|
328
|
+ %Client{token: %{refresh_token: refresh_token}} = client,
|
329
|
+ params,
|
330
|
+ headers,
|
331
|
+ opts
|
332
|
+ ) do
|
316
333
|
refresh_client =
|
317
334
|
%{client | strategy: OAuth2.Strategy.Refresh, token: nil}
|
318
335
|
|> Client.put_param(:refresh_token, refresh_token)
|
|
@@ -324,14 +341,16 @@ defmodule OAuth2.Client do
|
324
341
|
else
|
325
342
|
{:ok, put_in(client.token.refresh_token, refresh_token)}
|
326
343
|
end
|
327
|
- {:error, error} -> {:error, error}
|
344
|
+
|
345
|
+ {:error, error} ->
|
346
|
+ {:error, error}
|
328
347
|
end
|
329
348
|
end
|
330
349
|
|
331
350
|
@doc """
|
332
351
|
Calls `refresh_token/4` but raises `Error` if there an error occurs.
|
333
352
|
"""
|
334
|
- @spec refresh_token!(t, params, headers, Keyword.t) :: Client.t | Error.t
|
353
|
+ @spec refresh_token!(t, params, headers, Keyword.t()) :: Client.t() | Error.t()
|
335
354
|
def refresh_token!(%Client{} = client, params \\ [], headers \\ [], opts \\ []) do
|
336
355
|
case refresh_token(client, params, headers, opts) do
|
337
356
|
{:ok, %Client{} = client} -> client
|
|
@@ -351,7 +370,8 @@ defmodule OAuth2.Client do
|
351
370
|
Makes a `GET` request to the given `url` using the `OAuth2.AccessToken`
|
352
371
|
struct.
|
353
372
|
"""
|
354
|
- @spec get(t, binary, headers, Keyword.t) :: {:ok, Response.t} | {:error, Response.t} | {:error, Error.t}
|
373
|
+ @spec get(t, binary, headers, Keyword.t()) ::
|
374
|
+ {:ok, Response.t()} | {:error, Response.t()} | {:error, Error.t()}
|
355
375
|
def get(%Client{} = client, url, headers \\ [], opts \\ []),
|
356
376
|
do: Request.request(:get, client, url, "", headers, opts)
|
357
377
|
|
|
@@ -359,7 +379,7 @@ defmodule OAuth2.Client do
|
359
379
|
Same as `get/4` but returns a `OAuth2.Response` or `OAuth2.Error` exception if
|
360
380
|
the request results in an error.
|
361
381
|
"""
|
362
|
- @spec get!(t, binary, headers, Keyword.t) :: Response.t | Error.t
|
382
|
+ @spec get!(t, binary, headers, Keyword.t()) :: Response.t() | Error.t()
|
363
383
|
def get!(%Client{} = client, url, headers \\ [], opts \\ []),
|
364
384
|
do: Request.request!(:get, client, url, "", headers, opts)
|
365
385
|
|
|
@@ -367,7 +387,8 @@ defmodule OAuth2.Client do
|
367
387
|
Makes a `PUT` request to the given `url` using the `OAuth2.AccessToken`
|
368
388
|
struct.
|
369
389
|
"""
|
370
|
- @spec put(t, binary, body, headers, Keyword.t) :: {:ok, Response.t} | {:error, Response.t} | {:error, Error.t}
|
390
|
+ @spec put(t, binary, body, headers, Keyword.t()) ::
|
391
|
+ {:ok, Response.t()} | {:error, Response.t()} | {:error, Error.t()}
|
371
392
|
def put(%Client{} = client, url, body \\ "", headers \\ [], opts \\ []),
|
372
393
|
do: Request.request(:put, client, url, body, headers, opts)
|
373
394
|
|
|
@@ -378,7 +399,7 @@ defmodule OAuth2.Client do
|
378
399
|
An `OAuth2.Error` exception is raised if the request results in an
|
379
400
|
error tuple (`{:error, reason}`).
|
380
401
|
"""
|
381
|
- @spec put!(t, binary, body, headers, Keyword.t) :: Response.t | Error.t
|
402
|
+ @spec put!(t, binary, body, headers, Keyword.t()) :: Response.t() | Error.t()
|
382
403
|
def put!(%Client{} = client, url, body \\ "", headers \\ [], opts \\ []),
|
383
404
|
do: Request.request!(:put, client, url, body, headers, opts)
|
384
405
|
|
|
@@ -386,7 +407,8 @@ defmodule OAuth2.Client do
|
386
407
|
Makes a `PATCH` request to the given `url` using the `OAuth2.AccessToken`
|
387
408
|
struct.
|
388
409
|
"""
|
389
|
- @spec patch(t, binary, body, headers, Keyword.t) :: {:ok, Response.t} | {:error, Response.t} | {:error, Error.t}
|
410
|
+ @spec patch(t, binary, body, headers, Keyword.t()) ::
|
411
|
+ {:ok, Response.t()} | {:error, Response.t()} | {:error, Error.t()}
|
390
412
|
def patch(%Client{} = client, url, body \\ "", headers \\ [], opts \\ []),
|
391
413
|
do: Request.request(:patch, client, url, body, headers, opts)
|
392
414
|
|
|
@@ -397,14 +419,15 @@ defmodule OAuth2.Client do
|
397
419
|
An `OAuth2.Error` exception is raised if the request results in an
|
398
420
|
error tuple (`{:error, reason}`).
|
399
421
|
"""
|
400
|
- @spec patch!(t, binary, body, headers, Keyword.t) :: Response.t | Error.t
|
422
|
+ @spec patch!(t, binary, body, headers, Keyword.t()) :: Response.t() | Error.t()
|
401
423
|
def patch!(%Client{} = client, url, body \\ "", headers \\ [], opts \\ []),
|
402
424
|
do: Request.request!(:patch, client, url, body, headers, opts)
|
403
425
|
|
404
426
|
@doc """
|
405
427
|
Makes a `POST` request to the given URL using the `OAuth2.AccessToken`.
|
406
428
|
"""
|
407
|
- @spec post(t, binary, body, headers, Keyword.t) :: {:ok, Response.t} | {:error, Response.t} | {:error, Error.t}
|
429
|
+ @spec post(t, binary, body, headers, Keyword.t()) ::
|
430
|
+ {:ok, Response.t()} | {:error, Response.t()} | {:error, Error.t()}
|
408
431
|
def post(%Client{} = client, url, body \\ "", headers \\ [], opts \\ []),
|
409
432
|
do: Request.request(:post, client, url, body, headers, opts)
|
410
433
|
|
|
@@ -415,14 +438,15 @@ defmodule OAuth2.Client do
|
415
438
|
An `OAuth2.Error` exception is raised if the request results in an
|
416
439
|
error tuple (`{:error, reason}`).
|
417
440
|
"""
|
418
|
- @spec post!(t, binary, body, headers, Keyword.t) :: Response.t | Error.t
|
441
|
+ @spec post!(t, binary, body, headers, Keyword.t()) :: Response.t() | Error.t()
|
419
442
|
def post!(%Client{} = client, url, body \\ "", headers \\ [], opts \\ []),
|
420
443
|
do: Request.request!(:post, client, url, body, headers, opts)
|
421
444
|
|
422
445
|
@doc """
|
423
446
|
Makes a `DELETE` request to the given URL using the `OAuth2.AccessToken`.
|
424
447
|
"""
|
425
|
- @spec delete(t, binary, body, headers, Keyword.t) :: {:ok, Response.t} | {:error, Response.t} | {:error, Error.t}
|
448
|
+ @spec delete(t, binary, body, headers, Keyword.t()) ::
|
449
|
+ {:ok, Response.t()} | {:error, Response.t()} | {:error, Error.t()}
|
426
450
|
def delete(%Client{} = client, url, body \\ "", headers \\ [], opts \\ []),
|
427
451
|
do: Request.request(:delete, client, url, body, headers, opts)
|
428
452
|
|
|
@@ -433,7 +457,7 @@ defmodule OAuth2.Client do
|
433
457
|
An `OAuth2.Error` exception is raised if the request results in an
|
434
458
|
error tuple (`{:error, reason}`).
|
435
459
|
"""
|
436
|
- @spec delete!(t, binary, body, headers, Keyword.t) :: Response.t | Error.t
|
460
|
+ @spec delete!(t, binary, body, headers, Keyword.t()) :: Response.t() | Error.t()
|
437
461
|
def delete!(%Client{} = client, url, body \\ "", headers \\ [], opts \\ []),
|
438
462
|
do: Request.request!(:delete, client, url, body, headers, opts)
|
439
463
|
|
|
@@ -454,11 +478,13 @@ defmodule OAuth2.Client do
|
454
478
|
|> to_url(:token_url)
|
455
479
|
end
|
456
480
|
|
457
|
- defp token_post_header(%Client{token_method: :post} = client), do:
|
458
|
- put_header(client, "content-type", "application/x-www-form-urlencoded")
|
481
|
+ defp token_post_header(%Client{token_method: :post} = client),
|
482
|
+ do: put_header(client, "content-type", "application/x-www-form-urlencoded")
|
483
|
+
|
459
484
|
defp token_post_header(%Client{} = client), do: client
|
460
485
|
|
461
486
|
defp endpoint(client, <<"/"::utf8, _::binary>> = endpoint),
|
462
487
|
do: client.site <> endpoint
|
488
|
+
|
463
489
|
defp endpoint(_client, endpoint), do: endpoint
|
464
490
|
end
|
changed
lib/oauth2/error.ex
|
@@ -2,12 +2,12 @@ defmodule OAuth2.Error do
|
2
2
|
@moduledoc false
|
3
3
|
|
4
4
|
@type t :: %__MODULE__{
|
5
|
- reason: binary
|
6
|
- }
|
5
|
+ reason: binary
|
6
|
+ }
|
7
7
|
|
8
8
|
defexception [:reason]
|
9
9
|
|
10
10
|
def message(%__MODULE__{reason: :econnrefused}), do: "Connection refused"
|
11
11
|
def message(%__MODULE__{reason: reason}) when is_binary(reason), do: reason
|
12
|
- def message(%__MODULE__{reason: reason}), do: inspect reason
|
12
|
+ def message(%__MODULE__{reason: reason}), do: inspect(reason)
|
13
13
|
end
|
changed
lib/oauth2/request.ex
|
@@ -11,11 +11,11 @@ defmodule OAuth2.Request do
|
11
11
|
@doc """
|
12
12
|
Makes a request of given type to the given URL using the `OAuth2.AccessToken`.
|
13
13
|
"""
|
14
|
- @spec request(atom, Client.t, binary, body, Client.headers, Keyword.t)
|
15
|
- :: {:ok, Response.t} | {:error, Response.t} | {:error, Error.t}
|
14
|
+ @spec request(atom, Client.t(), binary, body, Client.headers(), Keyword.t()) ::
|
15
|
+ {:ok, Response.t()} | {:ok, reference} | {:error, Response.t()} | {:error, Error.t()}
|
16
16
|
def request(method, %Client{} = client, url, body, headers, opts) do
|
17
17
|
url = client |> process_url(url) |> process_params(opts[:params])
|
18
|
- headers = req_headers(client, headers) |> Enum.uniq
|
18
|
+ headers = req_headers(client, headers) |> Enum.uniq()
|
19
19
|
content_type = content_type(headers)
|
20
20
|
serializer = Client.get_serializer(client, content_type)
|
21
21
|
body = encode_request_body(body, content_type, serializer)
|
|
@@ -25,21 +25,24 @@ defmodule OAuth2.Request do
|
25
25
|
if Application.get_env(:oauth2, :debug) do
|
26
26
|
Logger.debug("""
|
27
27
|
OAuth2 Provider Request
|
28
|
- url: #{inspect url}
|
29
|
- method: #{inspect method}
|
30
|
- headers: #{inspect headers}
|
31
|
- body: #{inspect body}
|
32
|
- req_opts: #{inspect req_opts}
|
28
|
+ url: #{inspect(url)}
|
29
|
+ method: #{inspect(method)}
|
30
|
+ headers: #{inspect(headers)}
|
31
|
+ body: #{inspect(body)}
|
32
|
+ req_opts: #{inspect(req_opts)}
|
33
33
|
""")
|
34
34
|
end
|
35
35
|
|
36
36
|
case :hackney.request(method, url, headers, body, req_opts) do
|
37
37
|
{:ok, ref} when is_reference(ref) ->
|
38
38
|
{:ok, ref}
|
39
|
+
|
39
40
|
{:ok, status, headers, ref} when is_reference(ref) ->
|
40
41
|
process_body(client, status, headers, ref)
|
42
|
+
|
41
43
|
{:ok, status, headers, body} when is_binary(body) ->
|
42
44
|
process_body(client, status, headers, body)
|
45
|
+
|
43
46
|
{:error, reason} ->
|
44
47
|
{:error, %Error{reason: reason}}
|
45
48
|
end
|
|
@@ -52,22 +55,26 @@ defmodule OAuth2.Request do
|
52
55
|
An `OAuth2.Error` exception is raised if the request results in an
|
53
56
|
error tuple (`{:error, reason}`).
|
54
57
|
"""
|
55
|
- @spec request!(atom, Client.t, binary, body, Client.headers, Keyword.t) :: Response.t
|
58
|
+ @spec request!(atom, Client.t(), binary, body, Client.headers(), Keyword.t()) :: Response.t()
|
56
59
|
def request!(method, %Client{} = client, url, body, headers, opts) do
|
57
60
|
case request(method, client, url, body, headers, opts) do
|
58
61
|
{:ok, resp} ->
|
59
62
|
resp
|
63
|
+
|
60
64
|
{:error, %Response{status_code: code, headers: headers, body: body}} ->
|
61
|
- raise %Error{reason: """
|
62
|
- Server responded with status: #{code}
|
65
|
+ raise %Error{
|
66
|
+ reason: """
|
67
|
+ Server responded with status: #{code}
|
63
68
|
|
64
|
- Headers:
|
69
|
+ Headers:
|
65
70
|
|
66
|
- #{Enum.reduce(headers, "", fn {k, v}, acc -> acc <> "#{k}: #{v}\n" end)}
|
67
|
- Body:
|
71
|
+ #{Enum.reduce(headers, "", fn {k, v}, acc -> acc <> "#{k}: #{v}\n" end)}
|
72
|
+ Body:
|
73
|
+
|
74
|
+ #{inspect(body)}
|
75
|
+ """
|
76
|
+ }
|
68
77
|
|
69
|
- #{inspect body}
|
70
|
- """}
|
71
78
|
{:error, error} ->
|
72
79
|
raise error
|
73
80
|
end
|
|
@@ -85,15 +92,19 @@ defmodule OAuth2.Request do
|
85
92
|
case :hackney.body(ref) do
|
86
93
|
{:ok, body} ->
|
87
94
|
process_body(client, status, headers, body)
|
95
|
+
|
88
96
|
{:error, reason} ->
|
89
97
|
{:error, %Error{reason: reason}}
|
90
98
|
end
|
91
99
|
end
|
100
|
+
|
92
101
|
defp process_body(client, status, headers, body) when is_binary(body) do
|
93
102
|
resp = Response.new(client, status, headers, body)
|
103
|
+
|
94
104
|
case status do
|
95
105
|
status when status in 200..399 ->
|
96
106
|
{:ok, resp}
|
107
|
+
|
97
108
|
status when status in 400..599 ->
|
98
109
|
{:error, resp}
|
99
110
|
end
|
|
@@ -101,11 +112,13 @@ defmodule OAuth2.Request do
|
101
112
|
|
102
113
|
defp process_params(url, nil),
|
103
114
|
do: url
|
115
|
+
|
104
116
|
defp process_params(url, params),
|
105
117
|
do: url <> "?" <> URI.encode_query(params)
|
106
118
|
|
107
119
|
defp req_headers(%Client{token: nil} = client, headers),
|
108
120
|
do: headers ++ client.headers
|
121
|
+
|
109
122
|
defp req_headers(%Client{token: token} = client, headers),
|
110
123
|
do: [authorization_header(token) | headers] ++ client.headers
|
111
124
|
|
|
@@ -116,6 +129,7 @@ defmodule OAuth2.Request do
|
116
129
|
case List.keyfind(headers, "accept", 0) do
|
117
130
|
{"accept", _} ->
|
118
131
|
headers
|
132
|
+
|
119
133
|
nil ->
|
120
134
|
[{"accept", content_type} | headers]
|
121
135
|
end
|
|
@@ -123,11 +137,14 @@ defmodule OAuth2.Request do
|
123
137
|
|
124
138
|
defp encode_request_body("", _, _), do: ""
|
125
139
|
defp encode_request_body([], _, _), do: ""
|
140
|
+
|
126
141
|
defp encode_request_body(body, "application/x-www-form-urlencoded", _),
|
127
142
|
do: URI.encode_query(body)
|
143
|
+
|
128
144
|
defp encode_request_body(body, _mime, nil) do
|
129
145
|
body
|
130
146
|
end
|
147
|
+
|
131
148
|
defp encode_request_body(body, _mime, serializer) do
|
132
149
|
serializer.encode!(body)
|
133
150
|
end
|
changed
lib/oauth2/response.ex
|
@@ -15,18 +15,19 @@ defmodule OAuth2.Response do
|
15
15
|
alias OAuth2.Client
|
16
16
|
|
17
17
|
@type status_code :: integer
|
18
|
- @type headers :: list
|
19
|
- @type body :: binary | map
|
18
|
+ @type headers :: [{binary, binary}]
|
19
|
+ @type body :: binary | map | list
|
20
20
|
|
21
21
|
@type t :: %__MODULE__{
|
22
|
- status_code: status_code,
|
23
|
- headers: headers,
|
24
|
- body: body
|
25
|
- }
|
22
|
+ status_code: status_code,
|
23
|
+ headers: headers,
|
24
|
+ body: body
|
25
|
+ }
|
26
26
|
|
27
27
|
defstruct status_code: nil, headers: [], body: nil
|
28
28
|
|
29
29
|
@doc false
|
30
|
+ @spec new(Client.t(), integer, headers, body) :: t
|
30
31
|
def new(client, code, headers, body) do
|
31
32
|
headers = process_headers(headers)
|
32
33
|
content_type = content_type(headers)
|
|
@@ -35,7 +36,7 @@ defmodule OAuth2.Response do
|
35
36
|
resp = %__MODULE__{status_code: code, headers: headers, body: body}
|
36
37
|
|
37
38
|
if Application.get_env(:oauth2, :debug) do
|
38
|
- Logger.debug("OAuth2 Provider Response #{inspect resp}")
|
39
|
+ Logger.debug("OAuth2 Provider Response #{inspect(resp)}")
|
39
40
|
end
|
40
41
|
|
41
42
|
resp
|
|
@@ -47,9 +48,11 @@ defmodule OAuth2.Response do
|
47
48
|
|
48
49
|
defp decode_response_body("", _type, _), do: ""
|
49
50
|
defp decode_response_body(" ", _type, _), do: ""
|
51
|
+
|
50
52
|
defp decode_response_body(body, _type, serializer) when serializer != nil do
|
51
53
|
serializer.decode!(body)
|
52
54
|
end
|
55
|
+
|
53
56
|
# Facebook sends text/plain tokens!?
|
54
57
|
defp decode_response_body(body, "text/plain", _) do
|
55
58
|
case URI.decode_query(body) do
|
|
@@ -57,9 +60,11 @@ defmodule OAuth2.Response do
|
57
60
|
_ -> body
|
58
61
|
end
|
59
62
|
end
|
63
|
+
|
60
64
|
defp decode_response_body(body, "application/x-www-form-urlencoded", _) do
|
61
65
|
URI.decode_query(body)
|
62
66
|
end
|
67
|
+
|
63
68
|
defp decode_response_body(body, _mime, nil) do
|
64
69
|
body
|
65
70
|
end
|
changed
lib/oauth2/strategy.ex
|
@@ -78,10 +78,10 @@ defmodule OAuth2.Strategy do
|
78
78
|
|> merge_params(params)
|
79
79
|
end
|
80
80
|
"""
|
81
|
- @callback authorize_url(Client.t, Client.params) :: Client.t
|
81
|
+ @callback authorize_url(Client.t(), Client.params()) :: Client.t()
|
82
82
|
|
83
83
|
@doc """
|
84
|
- Builds the URL to token endpoint.
|
84
|
+ Builds the URL to the token endpoint.
|
85
85
|
|
86
86
|
## Example
|
87
87
|
|
|
@@ -96,7 +96,7 @@ defmodule OAuth2.Strategy do
|
96
96
|
|> put_headers(headers)
|
97
97
|
end
|
98
98
|
"""
|
99
|
- @callback get_token(Client.t, Client.params, Client.headers) :: Client.t
|
99
|
+ @callback get_token(Client.t(), Client.params(), Client.headers()) :: Client.t()
|
100
100
|
|
101
101
|
defmacro __using__(_) do
|
102
102
|
quote do
|
changed
lib/oauth2/strategy/auth_code.ex
|
@@ -30,6 +30,7 @@ defmodule OAuth2.Strategy.AuthCode do
|
30
30
|
The authorization URL endpoint of the provider.
|
31
31
|
params additional query parameters for the URL
|
32
32
|
"""
|
33
|
+ @impl true
|
33
34
|
def authorize_url(client, params) do
|
34
35
|
client
|
35
36
|
|> put_param(:response_type, "code")
|
|
@@ -41,11 +42,12 @@ defmodule OAuth2.Strategy.AuthCode do
|
41
42
|
@doc """
|
42
43
|
Retrieve an access token given the specified validation code.
|
43
44
|
"""
|
45
|
+ @impl true
|
44
46
|
def get_token(client, params, headers) do
|
45
47
|
{code, params} = Keyword.pop(params, :code, client.params["code"])
|
46
48
|
|
47
49
|
unless code do
|
48
|
- raise OAuth2.Error, reason: "Missing required key `code` for `#{inspect __MODULE__}`"
|
50
|
+ raise OAuth2.Error, reason: "Missing required key `code` for `#{inspect(__MODULE__)}`"
|
49
51
|
end
|
50
52
|
|
51
53
|
client
|
|
@@ -54,7 +56,7 @@ defmodule OAuth2.Strategy.AuthCode do
|
54
56
|
|> put_param(:client_id, client.client_id)
|
55
57
|
|> put_param(:redirect_uri, client.redirect_uri)
|
56
58
|
|> merge_params(params)
|
59
|
+ |> basic_auth()
|
57
60
|
|> put_headers(headers)
|
58
61
|
end
|
59
62
|
end
|
60
|
-
|
changed
lib/oauth2/strategy/client_credentials.ex
|
@@ -20,6 +20,7 @@ defmodule OAuth2.Strategy.ClientCredentials do
|
20
20
|
@doc """
|
21
21
|
Not used for this strategy.
|
22
22
|
"""
|
23
|
+ @impl true
|
23
24
|
def authorize_url(_client, _params) do
|
24
25
|
raise OAuth2.Error, reason: "This strategy does not implement `authorize_url`."
|
25
26
|
end
|
|
@@ -27,6 +28,7 @@ defmodule OAuth2.Strategy.ClientCredentials do
|
27
28
|
@doc """
|
28
29
|
Retrieve an access token given the specified strategy.
|
29
30
|
"""
|
31
|
+ @impl true
|
30
32
|
def get_token(client, params, headers) do
|
31
33
|
{auth_scheme, params} = Keyword.pop(params, :auth_scheme, "auth_header")
|
32
34
|
|
|
@@ -37,17 +39,12 @@ defmodule OAuth2.Strategy.ClientCredentials do
|
37
39
|
|> put_headers(headers)
|
38
40
|
end
|
39
41
|
|
40
|
- defp auth_scheme(client, "auth_header"), do: auth_header(client)
|
42
|
+ defp auth_scheme(client, "auth_header"), do: basic_auth(client)
|
41
43
|
defp auth_scheme(client, "request_body"), do: request_body(client)
|
42
44
|
|
43
|
- defp auth_header(%{client_id: id, client_secret: secret} = client) do
|
44
|
- put_header(client, "Authorization", "Basic " <> Base.encode64(id <> ":" <> secret))
|
45
|
- end
|
46
|
-
|
47
45
|
defp request_body(client) do
|
48
46
|
client
|
49
47
|
|> put_param(:client_id, client.client_id)
|
50
48
|
|> put_param(:client_secret, client.client_secret)
|
51
49
|
end
|
52
50
|
end
|
53
|
-
|
changed
lib/oauth2/strategy/password.ex
|
@@ -25,6 +25,7 @@ defmodule OAuth2.Strategy.Password do
|
25
25
|
@doc """
|
26
26
|
Not used for this strategy.
|
27
27
|
"""
|
28
|
+ @impl true
|
28
29
|
def authorize_url(_client, _params) do
|
29
30
|
raise OAuth2.Error, reason: "This strategy does not implement `authorize_url`."
|
30
31
|
end
|
|
@@ -32,21 +33,22 @@ defmodule OAuth2.Strategy.Password do
|
32
33
|
@doc """
|
33
34
|
Retrieve an access token given the specified End User username and password.
|
34
35
|
"""
|
36
|
+ @impl true
|
35
37
|
def get_token(client, params, headers) do
|
36
38
|
{username, params} = Keyword.pop(params, :username, client.params["username"])
|
37
39
|
{password, params} = Keyword.pop(params, :password, client.params["password"])
|
38
40
|
|
39
41
|
unless username && password do
|
40
|
- raise OAuth2.Error, reason: "Missing required keys `username` and `password` for #{inspect __MODULE__}"
|
42
|
+ raise OAuth2.Error,
|
43
|
+ reason: "Missing required keys `username` and `password` for #{inspect(__MODULE__)}"
|
41
44
|
end
|
42
45
|
|
43
46
|
client
|
44
47
|
|> put_param(:username, username)
|
45
48
|
|> put_param(:password, password)
|
46
49
|
|> put_param(:grant_type, "password")
|
47
|
- |> put_param(:client_id, client.client_id)
|
48
|
- |> put_param(:client_secret, client.client_secret)
|
49
50
|
|> merge_params(params)
|
51
|
+ |> basic_auth()
|
50
52
|
|> put_headers(headers)
|
51
53
|
end
|
52
54
|
end
|
changed
lib/oauth2/strategy/refresh.ex
|
@@ -27,6 +27,7 @@ defmodule OAuth2.Strategy.Refresh do
|
27
27
|
@doc """
|
28
28
|
Not used for this strategy.
|
29
29
|
"""
|
30
|
+ @impl true
|
30
31
|
def authorize_url(_client, _params) do
|
31
32
|
raise OAuth2.Error, reason: "This strategy does not implement `authorize_url`."
|
32
33
|
end
|
|
@@ -34,19 +35,20 @@ defmodule OAuth2.Strategy.Refresh do
|
34
35
|
@doc """
|
35
36
|
Refresh an access token given the specified validation code.
|
36
37
|
"""
|
38
|
+ @impl true
|
37
39
|
def get_token(client, params, headers) do
|
38
40
|
{token, params} = Keyword.pop(params, :refresh_token, client.params["refresh_token"])
|
39
41
|
|
40
42
|
unless token do
|
41
|
- raise OAuth2.Error, reason: "Missing required key `refresh_token` for `#{inspect __MODULE__}`"
|
43
|
+ raise OAuth2.Error,
|
44
|
+ reason: "Missing required key `refresh_token` for `#{inspect(__MODULE__)}`"
|
42
45
|
end
|
43
46
|
|
44
47
|
client
|
45
48
|
|> put_param(:refresh_token, token)
|
46
49
|
|> put_param(:grant_type, "refresh_token")
|
47
|
- |> put_param(:client_id, client.client_id)
|
48
|
- |> put_param(:client_secret, client.client_secret)
|
49
50
|
|> merge_params(params)
|
51
|
+ |> basic_auth()
|
50
52
|
|> put_headers(headers)
|
51
53
|
end
|
52
54
|
end
|
changed
lib/oauth2/util.ex
|
@@ -1,17 +1,20 @@
|
1
1
|
defmodule OAuth2.Util do
|
2
2
|
@moduledoc false
|
3
3
|
|
4
|
+ @spec unix_now :: integer
|
4
5
|
def unix_now do
|
5
|
- {mega, sec, _micro} = :os.timestamp
|
6
|
- (mega * 1_000_000) + sec
|
6
|
+ {mega, sec, _micro} = :os.timestamp()
|
7
|
+ mega * 1_000_000 + sec
|
7
8
|
end
|
8
9
|
|
10
|
+ @spec content_type([{binary, binary}]) :: binary
|
9
11
|
def content_type(headers) do
|
10
12
|
case get_content_type(headers) do
|
11
13
|
{_, content_type} ->
|
12
14
|
content_type
|
13
15
|
|> remove_params
|
14
16
|
|> parse_content_type
|
17
|
+
|
15
18
|
nil ->
|
16
19
|
"application/json"
|
17
20
|
end
|
|
@@ -26,8 +29,9 @@ defmodule OAuth2.Util do
|
26
29
|
case String.split(content_type, "/") do
|
27
30
|
[type, subtype] ->
|
28
31
|
type <> "/" <> subtype
|
29
|
- [bad_type] ->
|
30
|
- raise OAuth2.Error, reason: "bad content-type: #{bad_type}"
|
32
|
+
|
33
|
+ _ ->
|
34
|
+ raise OAuth2.Error, reason: "bad content-type: #{content_type}"
|
31
35
|
end
|
32
36
|
end
|
changed
mix.exs
|
@@ -1,24 +1,27 @@
|
1
1
|
defmodule OAuth2.Mixfile do
|
2
2
|
use Mix.Project
|
3
3
|
|
4
|
- @version "1.0.1"
|
4
|
+ @version "2.0.0"
|
5
5
|
|
6
6
|
def project do
|
7
|
- [app: :oauth2,
|
8
|
- name: "OAuth2",
|
9
|
- version: @version,
|
10
|
- elixir: "~> 1.2",
|
11
|
- deps: deps(),
|
12
|
- package: package(),
|
13
|
- description: description(),
|
14
|
- docs: docs(),
|
15
|
- elixirc_paths: elixirc_paths(Mix.env),
|
16
|
- test_coverage: [tool: ExCoveralls],
|
17
|
- preferred_cli_env: [
|
18
|
- coveralls: :test,
|
19
|
- "coveralls.detail": :test,
|
20
|
- docs: :dev
|
21
|
- ]]
|
7
|
+ [
|
8
|
+ app: :oauth2,
|
9
|
+ name: "OAuth2",
|
10
|
+ version: @version,
|
11
|
+ elixir: "~> 1.2",
|
12
|
+ deps: deps(),
|
13
|
+ package: package(),
|
14
|
+ description: description(),
|
15
|
+ docs: docs(),
|
16
|
+ elixirc_paths: elixirc_paths(Mix.env()),
|
17
|
+ test_coverage: [tool: ExCoveralls],
|
18
|
+ preferred_cli_env: [
|
19
|
+ coveralls: :test,
|
20
|
+ "coveralls.detail": :test,
|
21
|
+ "coveralls.html": :test,
|
22
|
+ docs: :dev
|
23
|
+ ]
|
24
|
+ ]
|
22
25
|
end
|
23
26
|
|
24
27
|
def application do
|
|
@@ -26,17 +29,20 @@ defmodule OAuth2.Mixfile do
|
26
29
|
end
|
27
30
|
|
28
31
|
defp deps do
|
29
|
- [{:hackney, "~> 1.13"},
|
32
|
+ [
|
33
|
+ {:hackney, "~> 1.13"},
|
30
34
|
|
31
|
- # Test dependencies
|
32
|
- {:jason, "~> 1.0", only: :test},
|
33
|
- {:bypass, "~> 0.9", only: :test},
|
34
|
- {:plug_cowboy, "~> 1.0", only: :test},
|
35
|
- {:excoveralls, "~> 0.9", only: :test},
|
36
|
- {:dialyxir, "~> 0.5", only: [:dev], runtime: false},
|
35
|
+ # Test dependencies
|
36
|
+ {:jason, "~> 1.0", only: [:dev, :test]},
|
37
|
+ {:bypass, "~> 0.9", only: :test},
|
38
|
+ {:plug_cowboy, "~> 1.0", only: :test},
|
39
|
+ {:excoveralls, "~> 0.9", only: :test},
|
40
|
+ {:credo, "~> 1.1.0", only: [:dev, :test], runtime: false},
|
41
|
+ {:dialyxir, "~> 1.0.0-rc.6", only: [:dev], runtime: false},
|
37
42
|
|
38
|
- # Docs dependencies
|
39
|
- {:ex_doc, "~> 0.19", only: :dev}]
|
43
|
+ # Docs dependencies
|
44
|
+ {:ex_doc, "~> 0.19", only: :dev}
|
45
|
+ ]
|
40
46
|
end
|
41
47
|
|
42
48
|
defp description do
|
|
@@ -44,17 +50,21 @@ defmodule OAuth2.Mixfile do
|
44
50
|
end
|
45
51
|
|
46
52
|
defp docs do
|
47
|
- [extras: ["README.md"],
|
48
|
- main: "readme",
|
49
|
- source_ref: "v#{@version}",
|
50
|
- source_url: "https://github.com/scrogson/oauth2"]
|
53
|
+ [
|
54
|
+ extras: ["README.md"],
|
55
|
+ main: "readme",
|
56
|
+ source_ref: "v#{@version}",
|
57
|
+ source_url: "https://github.com/scrogson/oauth2"
|
58
|
+ ]
|
51
59
|
end
|
52
60
|
|
53
61
|
defp package do
|
54
|
- [files: ["lib", "mix.exs", "README.md", "LICENSE"],
|
55
|
- maintainers: ["Sonny Scroggin"],
|
56
|
- licenses: ["MIT"],
|
57
|
- links: %{github: "https://github.com/scrogson/oauth2"}]
|
62
|
+ [
|
63
|
+ files: ["lib", "mix.exs", "README.md", "LICENSE"],
|
64
|
+ maintainers: ["Sonny Scroggin"],
|
65
|
+ licenses: ["MIT"],
|
66
|
+ links: %{github: "https://github.com/scrogson/oauth2"}
|
67
|
+ ]
|
58
68
|
end
|
59
69
|
|
60
70
|
defp elixirc_paths(:test), do: ["lib", "test/support"]
|