Skip to content

Commit

Permalink
Merge pull request #8 from dwyl/google-token-#7
Browse files Browse the repository at this point in the history
Google token and user profile
  • Loading branch information
nelsonic authored Nov 20, 2019
2 parents 7f6ea4e + ae1b0db commit 2b1f9b0
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 7 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,16 @@ config :elixir_auth_google,
google_client_id: <YOUR-CLIENT-ID-HERE>,
google_scope: "profile",
google_redirect_uri: <REDIRECT_URI>,
```

- Create a new endpoint matching the `google_redirect_uri`.
On this endpoint you can exchange the google code for the user's token and
then get the user profile:

```eixir
def index(conn, %{"code" => code}) do
token = ElixirAuthGoogle.get_token(code)
profile = ElixirAuthGoogle.get_user_profile(token["access_token"])
render(conn, "index.html", profile: profile)
en
```
4 changes: 1 addition & 3 deletions config/config.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use Mix.Config

if Mix.env() == :test do
# define configuration specific to test environment
# It can be useful when testing/mocking
nil
config :elixir_auth_google, httpoison: ElixirAuthGoogle.HTTPoison.InMemory
end
37 changes: 35 additions & 2 deletions lib/elixir_auth_google.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,46 @@ defmodule ElixirAuthGoogle do
@moduledoc """
Minimalist Google OAuth Authentication for Elixir Apps
"""
@google_url "https://accounts.google.com/o/oauth2/v2/auth?response_type=code"
@httpoison Application.get_env(:elixir_auth_google, :httpoison) || HTTPoison
@google_auth_url "https://accounts.google.com/o/oauth2/v2/auth?response_type=code"
@google_token_url "https://oauth2.googleapis.com/token"
@google_user_profile "https://www.googleapis.com/oauth2/v3/userinfo"

def generate_oauth_url do
client_id = Application.get_env(:elixir_auth_google, :google_client_id)
scope = Application.get_env(:elixir_auth_google, :google_scope ) || "profile"
redirect_uri = Application.get_env(:elixir_auth_google, :google_redirect_uri)

"#{@google_url}&client_id=#{client_id}&scope=#{scope}&redirect_uri=#{redirect_uri}"
"#{@google_auth_url}&client_id=#{client_id}&scope=#{scope}&redirect_uri=#{redirect_uri}"
end

def get_token(code) do
body = Poison.encode!(
%{ client_id: Application.get_env(:elixir_auth_google, :google_client_id),
client_secret: Application.get_env(:elixir_auth_google, :google_client_secret),
redirect_uri: Application.get_env(:elixir_auth_google, :google_redirect_uri),
grant_type: "authorization_code",
code: code
})

@httpoison.post(@google_token_url, body)
|> parse_body_response()
end

def get_user_profile(token) do
"#{@google_user_profile}?access_token=#{token}"
|> @httpoison.get()
|> parse_body_response()
end

defp parse_body_response({:error, err}), do: {:error, err}
defp parse_body_response({:ok, response}) do
body = Map.get(response, :body)
if body == nil do
{:error, :no_body}
else
Poison.decode(body)
end
end

end
9 changes: 9 additions & 0 deletions lib/httpoison/in_memory.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule ElixirAuthGoogle.HTTPoison.InMemory do
def get("https://www.googleapis.com/oauth2/v3/userinfo?access_token=wrong_token") do
{:error, :bad_request}
end

def get(_url), do: {:ok, %{body: Poison.encode!(%{name: "dwyl"})}}

def post(_url, _body), do: {:ok, %{body: Poison.encode!(%{access_token: "token1"})}}
end
5 changes: 3 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule ElixirAuthGoogle.MixProject do
[
app: :elixir_auth_google,
version: @version,
elixir: "~> 1.8",
elixir: "~> 1.9",
start_permanent: Mix.env() == :prod,
deps: deps(),
description: @description,
Expand All @@ -26,7 +26,8 @@ defmodule ElixirAuthGoogle.MixProject do
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:httpoison, "~> 1.6"}
{:httpoison, "~> 1.6"},
{:poison, "~> 4.0"}
]
end

Expand Down
1 change: 1 addition & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"},
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"},
"poison": {:hex, :poison, "4.0.1", "bcb755a16fac91cad79bfe9fc3585bb07b9331e50cfe3420a24bcc2d735709ae", [:mix], [], "hexpm"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
}
12 changes: 12 additions & 0 deletions test/elixir_auth_google_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,16 @@ defmodule ElixirAuthGoogleTest do
Application.put_env(:elixir_auth_google, :google_client_id, 123)
assert ElixirAuthGoogle.generate_oauth_url() =~ "https://accounts.google.com/o/oauth2/v2/auth?response_type=code"
end

test "get Google token" do
assert ElixirAuthGoogle.get_token("ok_code") == {:ok, %{"access_token" => "token1"}}
end

test "get user profile" do
assert ElixirAuthGoogle.get_user_profile("123") == {:ok, %{"name" => "dwyl"}}
end

test "return error with incorrect token" do
assert ElixirAuthGoogle.get_user_profile("wrong_token") == {:error, :bad_request }
end
end

0 comments on commit 2b1f9b0

Please sign in to comment.