-
-
Notifications
You must be signed in to change notification settings - Fork 68
/
Copy pathex_oauth2_provider.ex
99 lines (81 loc) · 3.2 KB
/
ex_oauth2_provider.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
defmodule ExOauth2Provider do
@moduledoc """
A module that provides OAuth 2 capabilities for Elixir applications.
## Configuration
config :my_app, ExOauth2Provider,
repo: App.Repo,
resource_owner: App.Users.User,
default_scopes: ~w(public),
optional_scopes: ~w(write update),
native_redirect_uri: "urn:ietf:wg:oauth:2.0:oob",
authorization_code_expires_in: 600,
access_token_expires_in: 7200,
use_refresh_token: false,
revoke_refresh_token_on_use: false,
force_ssl_in_redirect_uri: true,
grant_flows: ~w(authorization_code client_credentials),
password_auth: nil,
access_token_response_body_handler: nil
If `revoke_refresh_token_on_use` is set to true,
refresh tokens will be revoked after a related access token is used.
If `revoke_refresh_token_on_use` is not set to true,
previous tokens are revoked as soon as a new access token is created.
If `use_refresh_token` is set to true, the refresh_token grant flow
is automatically enabled.
If `password_auth` is set to a {module, method} tuple, the password
grant flow is automatically enabled.
If access_token_expires_in is set to nil, access tokens will never
expire.
"""
alias ExOauth2Provider.{Config, AccessTokens}
@doc """
Authenticate an access token.
## Example
ExOauth2Provider.authenticate_token("Jf5rM8hQBc", otp_app: :my_app)
## Response
{:ok, access_token}
{:error, reason}
"""
@spec authenticate_token(binary(), keyword()) :: {:ok, map()} | {:error, any()}
def authenticate_token(token, config \\ [])
def authenticate_token(nil, _config), do: {:error, :token_inaccessible}
def authenticate_token(token, config) do
token
|> load_access_token(config)
|> maybe_revoke_previous_refresh_token(config)
|> validate_access_token()
|> load_resource_owner(config)
end
defp load_access_token(token, config) do
case AccessTokens.get_by_token(token, config) do
nil -> {:error, :token_not_found}
access_token -> {:ok, access_token}
end
end
defp maybe_revoke_previous_refresh_token({:error, error}, _config), do: {:error, error}
defp maybe_revoke_previous_refresh_token({:ok, access_token}, config) do
case Config.refresh_token_revoked_on_use?(config) do
true -> revoke_previous_refresh_token(access_token, config)
false -> {:ok, access_token}
end
end
defp revoke_previous_refresh_token(access_token, config) do
case AccessTokens.revoke_previous_refresh_token(access_token, config) do
{:error, _any} -> {:error, :no_association_found}
{:ok, _access_token} -> {:ok, access_token}
end
end
defp validate_access_token({:error, error}), do: {:error, error}
defp validate_access_token({:ok, access_token}) do
case AccessTokens.is_accessible?(access_token) do
true -> {:ok, access_token}
false -> {:error, :token_inaccessible}
end
end
defp load_resource_owner({:error, error}, _config), do: {:error, error}
defp load_resource_owner({:ok, access_token}, config) do
repo = Config.repo(config)
access_token = repo.preload(access_token, :resource_owner)
{:ok, access_token}
end
end