-
-
Notifications
You must be signed in to change notification settings - Fork 45
/
github.ex
75 lines (61 loc) · 2.18 KB
/
github.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
defmodule Assent.Strategy.Github do
@moduledoc """
Github OAuth 2.0 strategy.
## Configuration
- `:user_emails_url` - The API path or URL to fetch e-mails from, defaults to `/user/emails`
See `Assent.Strategy.OAuth2` for more.
## Usage
config = [
client_id: "REPLACE_WITH_CLIENT_ID",
client_secret: "REPLACE_WITH_CLIENT_SECRET"
]
See `Assent.Strategy.OAuth2` for more.
"""
use Assent.Strategy.OAuth2.Base
alias Assent.{Config, Strategy.OAuth2}
@impl true
def default_config(_config) do
[
site: "https://api.github.com",
authorize_url: "https://github.com/login/oauth/authorize",
token_url: "https://github.com/login/oauth/access_token",
user_url: "/user",
user_emails_url: "/user/emails",
authorization_params: [scope: "read:user,user:email"],
auth_method: :client_secret_post
]
end
@impl true
def normalize(_config, user) do
{:ok, %{
"sub" => user["id"],
"name" => user["name"],
"preferred_username" => user["login"],
"profile" => user["html_url"],
"picture" => user["avatar_url"],
"email" => user["email"],
"email_verified" => user["email_verified"]
}}
end
@impl true
def fetch_user(config, access_token) do
with {:ok, user_emails_url} <- Config.fetch(config, :user_emails_url),
{:ok, user} <- OAuth2.fetch_user(config, access_token) do
fetch_email(config, access_token, user, user_emails_url)
end
end
defp fetch_email(config, token, user, url) do
config
|> OAuth2.request(token, :get, url)
|> process_email_response(user)
end
defp process_email_response({:ok, %{body: emails}}, user) do
{email, verified} = get_primary_email(emails)
{:ok, Map.merge(user, %{"email" => email, "email_verified" => verified})}
end
defp process_email_response({:error, error}, _user), do: {:error, error}
defp get_primary_email([%{"verified" => verified, "primary" => true, "email" => email} | _rest]),
do: {email, verified}
defp get_primary_email([_ | rest]), do: get_primary_email(rest)
defp get_primary_email(_any), do: {nil, false}
end