Skip to content

Commit

Permalink
Merge pull request #169 from pow-auth/google-oidc
Browse files Browse the repository at this point in the history
Switch to Google OIDC
  • Loading branch information
danschultzer authored Dec 30, 2024
2 parents 2dc60fe + e175d03 commit 0647b8c
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 67 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

### Breaking changes

* `Assent.Strategy.Google` now return `hd` instead of `google_hd`
* `:site` configuration option removed, use `:base_url` instead
* `Assent.Strategy.OAuth2.authorize_url/2` no longer allows `:state` in `:authorization_params`
* `Assent.Strategy.decode_response/2`removed, use `Assent.HTTPAdapter.decode_response/2` instead
Expand All @@ -14,6 +15,10 @@
* `Assent.HTTPAdapter.Mint` removed
* `Assent.Config` removed

### Changes

* `Assent.Strategy.Google` now uses OIDC instead of OAuth 2.0 base strategy

## v0.2

The CHANGELOG for v0.2 releases can be found [in the v0.2 branch](https://github.com/pow-auth/assent/blob/v0.2/CHANGELOG.md).
38 changes: 7 additions & 31 deletions lib/assent/strategies/google.ex
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
defmodule Assent.Strategy.Google do
@moduledoc """
Google OAuth 2.0 strategy.
Google OpenID Connect strategy.
In the normalized user response a `google_hd` ("Hosted Domain") field is
In the normalized user response a `hd` ("Hosted Domain") field is
included in user parameters and can be used to limit access to users
belonging to a particular hosted domain.
Expand All @@ -22,44 +22,20 @@ defmodule Assent.Strategy.Google do
client_secret: "REPLACE_WITH_CLIENT_SECRET",
authorization_params: [
access_type: "offline",
scope: "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"
scope: "email profile"
]
]
See `Assent.Strategy.OAuth2` for more.
"""
use Assent.Strategy.OAuth2.Base
use Assent.Strategy.OIDC.Base

@impl true
def default_config(_config) do
[
base_url: "https://www.googleapis.com",
authorize_url: "https://accounts.google.com/o/oauth2/v2/auth",
token_url: "/oauth2/v4/token",
user_url: "/oauth2/v3/userinfo",
authorization_params: [
scope:
"https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"
],
auth_method: :client_secret_post
base_url: "https://accounts.google.com/",
authorization_params: [scope: "email profile"],
client_authentication_method: "client_secret_post"
]
end

@impl true
def normalize(_config, user) do
{:ok,
%{
"sub" => user["sub"],
"name" => user["name"],
"given_name" => user["given_name"],
"family_name" => user["family_name"],
"picture" => user["picture"],
"email" => user["email"],
"email_verified" => user["email_verified"],
"locale" => user["locale"]
},
%{
"google_hd" => user["hd"]
}}
end
end
6 changes: 1 addition & 5 deletions test/assent/strategies/azure_ad_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,7 @@ defmodule Assent.Strategy.AzureADTest do
"issuer",
"https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0"
)
|> Map.put("token_endpoint_auth_methods_supported", [
"client_secret_post",
"private_key_jwt",
"client_secret_basic"
])
|> Map.put("token_endpoint_auth_methods_supported", ["client_secret_post"])

session_params = Map.put(config[:session_params], :nonce, "123523")

Expand Down
66 changes: 38 additions & 28 deletions test/assent/strategies/google_test.exs
Original file line number Diff line number Diff line change
@@ -1,45 +1,55 @@
defmodule Assent.Strategy.GoogleTest do
use Assent.Test.OAuth2TestCase
use Assent.Test.OIDCTestCase

alias Assent.Strategy.Google

# From https://www.oauth.com/oauth2-servers/signing-in-with-google/verifying-the-user-info/
@user_response %{
"sub" => "110248495921238986420",
"name" => "Aaron Parecki",
"given_name" => "Aaron",
"family_name" => "Parecki",
"picture" =>
"https://lh4.googleusercontent.com/-kw-iMgD_j34/AAAAAAAAAAI/AAAAAAAAAAc/P1YY91tzesU/photo.jpg",
"email" => "[email protected]",
"email_verified" => true,
"locale" => "en",
"hd" => "okta.com"
# From https://developers.google.com/identity/openid-connect/openid-connect#obtainuserinfo
@id_token_claims %{
"iss" => "https://accounts.google.com",
"azp" => "1234987819200.apps.googleusercontent.com",
"aud" => "1234987819200.apps.googleusercontent.com",
"sub" => "10769150350006150715113082367",
"at_hash" => "HK6E_P6Dh8Y93mRNtsDB1Q",
"hd" => "example.com",
"email" => "[email protected]",
"email_verified" => "true",
"iat" => :os.system_time(:second),
"exp" => :os.system_time(:second) + 60,
"nonce" => "0394852-3190485-2490358"
}
@user %{
"email" => "[email protected]",
"email_verified" => true,
"family_name" => "Parecki",
"given_name" => "Aaron",
"google_hd" => "okta.com",
"name" => "Aaron Parecki",
"locale" => "en",
"picture" =>
"https://lh4.googleusercontent.com/-kw-iMgD_j34/AAAAAAAAAAI/AAAAAAAAAAc/P1YY91tzesU/photo.jpg",
"sub" => "110248495921238986420"
"email" => "[email protected]",
"email_verified" => "true",
"hd" => "example.com",
"sub" => "10769150350006150715113082367"
}

test "authorize_url/2", %{config: config} do
assert {:ok, %{url: url}} = Google.authorize_url(config)
assert url =~ "https://accounts.google.com/o/oauth2/v2/auth?client_id="

uri = URI.parse(url)

assert %{"client_id" => "id", "scope" => scope} = URI.decode_query(uri.query)
assert scope =~ "email profile"
end

test "callback/2", %{config: config, callback_params: params} do
expect_oauth2_access_token_request([uri: "/oauth2/v4/token"], fn _conn, params ->
assert params["client_secret"] == config[:client_secret]
end)
openid_config =
config[:openid_configuration]
|> Map.put("issuer", "https://accounts.google.com")
|> Map.put("token_endpoint_auth_methods_supported", ["client_secret_post"])

session_params = Map.put(config[:session_params], :nonce, "0394852-3190485-2490358")

config =
Keyword.merge(config,
openid_configuration: openid_config,
client_id: "1234987819200.apps.googleusercontent.com",
session_params: session_params
)

expect_oauth2_user_request(@user_response, uri: "/oauth2/v3/userinfo")
[key | _rest] = expect_oidc_jwks_uri_request()
expect_oidc_access_token_request(id_token_opts: [claims: @id_token_claims, kid: key["kid"]])

assert {:ok, %{user: user}} = Google.callback(config, params)
assert user == @user
Expand Down
6 changes: 3 additions & 3 deletions test/assent/strategies/twitch_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ defmodule Assent.Strategy.TwitchTest do
test "authorize_url/2", %{config: config} do
assert {:ok, %{url: url}} = Twitch.authorize_url(config)

url = URI.parse(url)
uri = URI.parse(url)

assert url.path == "/oauth/authorize"
assert uri.path == "/oauth/authorize"

assert %{"client_id" => "id", "scope" => scope, "claims" => claims} =
URI.decode_query(url.query)
URI.decode_query(uri.query)

assert scope =~ "user:read:email"

Expand Down

0 comments on commit 0647b8c

Please sign in to comment.