Skip to content

Commit

Permalink
Merge pull request #154 from tommasop/main
Browse files Browse the repository at this point in the history
Add Zitadel Strategy and implement PKCE
  • Loading branch information
danschultzer authored Dec 29, 2024
2 parents 1a04a45 + cf541d6 commit 7948f23
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* `Assent.Strategy.Bitbucket` added
* `Assent.Strategy.Twitch` added
* `Assent.Strategy.Telegram` added
* `Assent.Strategy.Zitadel` added
* `Assent.Strategy.Facebook.fetch_user/2` fixed bug with user not being decoded
* `Assent.Strategy.OAuth2` now supports PKCE
* `Assent.Strategy.OAuth2.Base.authorize_url/2` incomplete typespec fixed
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Multi-provider authentication framework.
* Twitch - `Assent.Strategy.Twitch`
* Twitter - `Assent.Strategy.Twitter`
* VK - `Assent.Strategy.VK`
* Zitadel - `Assent.Strategy.Zitadel`

## Installation

Expand Down
39 changes: 39 additions & 0 deletions lib/assent/strategies/zitadel.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
defmodule Assent.Strategy.Zitadel do
@moduledoc """
Zitadel Sign In OIDC strategy.
## Configuration
- `:resource_id` - The resource id, required
See `Assent.Strategy.OIDC` for more configuration options.
## Usage
config = [
base_url: "REPLACE_WITH_ORGANIZATION_URL",
client_id: "REPLACE_WITH_CLIENT_ID",
resource_id: "REPLACE_WITH_RESOURCE_ID"
]
"""
use Assent.Strategy.OIDC.Base

alias Assent.{Config, Strategy.OIDC}

@impl true
def default_config(config) do
trusted_audiences =
config
|> Config.get(:resource_id, nil)
|> List.wrap()

[
authorization_params: [scope: "email profile"],
client_authentication_method: "none",
code_verifier: true,
trusted_audiences: trusted_audiences
]
end

def fetch_user(config, token), do: OIDC.fetch_userinfo(config, token)
end
85 changes: 85 additions & 0 deletions test/assent/strategies/zitadel_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
defmodule Assent.Strategy.ZitadelTest do
use Assent.Test.OIDCTestCase

alias Assent.Strategy.Zitadel

@client_id "3425235252@nameofproject"
@resource_id "3425296767"
@id_token_claims %{
"iss" => "https://subdomain.region.zitadel.cloud",
"sub" => "299884084107794421",
"aud" => [@client_id, @resource_id],
"exp" => :os.system_time(:second) + 5 * 60,
"iat" => :os.system_time(:second),
"auth_time" => :os.system_time(:second) - 60,
"amr" => ["pwd"],
"azp" => @client_id,
"client_id" => @client_id,
"at_hash" => "at_hash",
"sid" => "sid"
}
@userinfo %{
"email" => "[email protected]",
"email_verified" => true,
"family_name" => "Admin",
"given_name" => "ZITADEL",
"locale" => "en",
"name" => "ZITADEL Admin",
"preferred_username" => "[email protected]",
"sub" => "299884084107794421",
"updated_at" => 1_735_240_843
}
@user %{
"sub" => "299884084107794421",
"email" => "[email protected]",
"email_verified" => true,
"family_name" => "Admin",
"given_name" => "ZITADEL",
"locale" => "en",
"name" => "ZITADEL Admin",
"preferred_username" => "[email protected]",
"updated_at" => 1_735_240_843
}

setup %{config: config} do
openid_configuration =
Map.put(config[:openid_configuration], "issuer", "https://subdomain.region.zitadel.cloud")

session_params = Map.put(config[:session_params], :code_verifier, "code_verifier_value")

config =
Keyword.merge(
config,
client_id: @client_id,
openid_configuration: openid_configuration,
session_params: session_params,
resource_id: @resource_id
)

{:ok, config: config}
end

test "authorize_url/2", %{config: config} do
assert {:ok, %{url: url, session_params: session_params}} = Zitadel.authorize_url(config)

assert session_params[:code_verifier]

url = URI.parse(url)

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

assert %{"client_id" => @client_id, "scope" => scope, "code_challenge_method" => "S256"} =
URI.decode_query(url.query)

assert scope =~ "email profile"
end

test "callback/2", %{config: config, callback_params: params} do
[key | _rest] = expect_oidc_jwks_uri_request()
expect_oidc_access_token_request(id_token_opts: [claims: @id_token_claims, kid: key["kid"]])
expect_oidc_userinfo_request(@userinfo)

assert {:ok, %{user: user}} = Zitadel.callback(config, params)
assert user == @user
end
end

0 comments on commit 7948f23

Please sign in to comment.