Skip to content

Commit

Permalink
FAPI 2.0 Certification
Browse files Browse the repository at this point in the history
  • Loading branch information
maennchen committed Apr 30, 2024
1 parent 701a863 commit f3c7735
Show file tree
Hide file tree
Showing 21 changed files with 300 additions and 91 deletions.
23 changes: 23 additions & 0 deletions artifacts/GENERATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generation of keys

```bash
# Generate Private Keys
openssl ecparam -genkey -name prime256v1 -noout -out artifacts/client.priv.pem
openssl ecparam -genkey -name prime256v1 -noout -out artifacts/server.priv.pem

# Generate Public Keys
openssl ec -in ./artifacts/client.priv.pem -pubout -out ./artifacts/client.pub.pem
openssl ec -in ./artifacts/server.priv.pem -pubout -out ./artifacts/server.pub.pem

# Generate JWKs for public & private keys
npx eckles ./artifacts/client.priv.pem > ./artifacts/client.priv.jwk
npx eckles ./artifacts/client.pub.pem > ./artifacts/client.pub.jwk
npx eckles ./artifacts/server.priv.pem > ./artifacts/server.priv.jwk
npx eckles ./artifacts/server.pub.pem > ./artifacts/server.pub.jwk

# Generate JWK sets
cat ./artifacts/client.priv.jwk| jq '{"keys": [. * {"use": "sig", "kid": "client", "alg": "ES256"}]}' > ./artifacts/client.priv.jwkset
cat ./artifacts/client.pub.jwk| jq '{"keys": [. * {"use": "sig", "kid": "client", "alg": "ES256"}]}' > ./artifacts/client.pub.jwkset
cat ./artifacts/server.priv.jwk| jq '{"keys": [. * {"use": "sig", "kid": "server", "alg": "ES256"}]}' > ./artifacts/server.priv.jwkset
cat ./artifacts/server.pub.jwk| jq '{"keys": [. * {"use": "sig", "kid": "server", "alg": "ES256"}]}' > ./artifacts/server.pub.jwkset
```
7 changes: 7 additions & 0 deletions artifacts/client.priv.jwk
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"kty": "EC",
"crv": "P-256",
"d": "I5XC9VN5oJUQpXO5LqN5jNm9NTPAo_8zUkiUhJlgoRk",
"x": "QaXzjB1aMQRoXcgFTQUneS6EBVaQHQObzaHJjKV6_fM",
"y": "fljC46dVTTQFsyB4Iap7pmTzolhLX2KOtajOI2kEh7g"
}
14 changes: 14 additions & 0 deletions artifacts/client.priv.jwkset
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"keys": [
{
"kty": "EC",
"crv": "P-256",
"d": "I5XC9VN5oJUQpXO5LqN5jNm9NTPAo_8zUkiUhJlgoRk",
"x": "QaXzjB1aMQRoXcgFTQUneS6EBVaQHQObzaHJjKV6_fM",
"y": "fljC46dVTTQFsyB4Iap7pmTzolhLX2KOtajOI2kEh7g",
"use": "sig",
"kid": "client",
"alg": "ES256"
}
]
}
5 changes: 5 additions & 0 deletions artifacts/client.priv.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEICOVwvVTeaCVEKVzuS6jeYzZvTUzwKP/M1JIlISZYKEZoAoGCCqGSM49
AwEHoUQDQgAEQaXzjB1aMQRoXcgFTQUneS6EBVaQHQObzaHJjKV6/fN+WMLjp1VN
NAWzIHghqnumZPOiWEtfYo61qM4jaQSHuA==
-----END EC PRIVATE KEY-----
6 changes: 6 additions & 0 deletions artifacts/client.pub.jwk
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"kty": "EC",
"crv": "P-256",
"x": "QaXzjB1aMQRoXcgFTQUneS6EBVaQHQObzaHJjKV6_fM",
"y": "fljC46dVTTQFsyB4Iap7pmTzolhLX2KOtajOI2kEh7g"
}
13 changes: 13 additions & 0 deletions artifacts/client.pub.jwkset
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"keys": [
{
"kty": "EC",
"crv": "P-256",
"x": "QaXzjB1aMQRoXcgFTQUneS6EBVaQHQObzaHJjKV6_fM",
"y": "fljC46dVTTQFsyB4Iap7pmTzolhLX2KOtajOI2kEh7g",
"use": "sig",
"kid": "client",
"alg": "ES256"
}
]
}
4 changes: 4 additions & 0 deletions artifacts/client.pub.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQaXzjB1aMQRoXcgFTQUneS6EBVaQ
HQObzaHJjKV6/fN+WMLjp1VNNAWzIHghqnumZPOiWEtfYo61qM4jaQSHuA==
-----END PUBLIC KEY-----
7 changes: 7 additions & 0 deletions artifacts/server.priv.jwk
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"kty": "EC",
"crv": "P-256",
"d": "6-YakWKMTt1LEZDlEuuUpKjrMuhpYEaFeors8RKdxr8",
"x": "-e56Pjr4gW6fk73WGO1hyldhEG7X4pnkD_U6Tclqe58",
"y": "RgLVVgsLbPeGZEZs2_9buxp6f8RqsJza37JQJZOySCM"
}
14 changes: 14 additions & 0 deletions artifacts/server.priv.jwkset
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"keys": [
{
"kty": "EC",
"crv": "P-256",
"d": "6-YakWKMTt1LEZDlEuuUpKjrMuhpYEaFeors8RKdxr8",
"x": "-e56Pjr4gW6fk73WGO1hyldhEG7X4pnkD_U6Tclqe58",
"y": "RgLVVgsLbPeGZEZs2_9buxp6f8RqsJza37JQJZOySCM",
"use": "sig",
"kid": "server",
"alg": "ES256"
}
]
}
5 changes: 5 additions & 0 deletions artifacts/server.priv.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIOvmGpFijE7dSxGQ5RLrlKSo6zLoaWBGhXqK7PESnca/oAoGCCqGSM49
AwEHoUQDQgAE+e56Pjr4gW6fk73WGO1hyldhEG7X4pnkD/U6Tclqe59GAtVWCwts
94ZkRmzb/1u7Gnp/xGqwnNrfslAlk7JIIw==
-----END EC PRIVATE KEY-----
6 changes: 6 additions & 0 deletions artifacts/server.pub.jwk
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"kty": "EC",
"crv": "P-256",
"x": "-e56Pjr4gW6fk73WGO1hyldhEG7X4pnkD_U6Tclqe58",
"y": "RgLVVgsLbPeGZEZs2_9buxp6f8RqsJza37JQJZOySCM"
}
13 changes: 13 additions & 0 deletions artifacts/server.pub.jwkset
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"keys": [
{
"kty": "EC",
"crv": "P-256",
"x": "-e56Pjr4gW6fk73WGO1hyldhEG7X4pnkD_U6Tclqe58",
"y": "RgLVVgsLbPeGZEZs2_9buxp6f8RqsJza37JQJZOySCM",
"use": "sig",
"kid": "server",
"alg": "ES256"
}
]
}
4 changes: 4 additions & 0 deletions artifacts/server.pub.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+e56Pjr4gW6fk73WGO1hyldhEG7X
4pnkD/U6Tclqe59GAtVWCwts94ZkRmzb/1u7Gnp/xGqwnNrfslAlk7JIIw==
-----END PUBLIC KEY-----
160 changes: 100 additions & 60 deletions lib/conformance/auth_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ defmodule Conformance.AuthController do

require Logger

alias Oidcc.ClientContext
alias Oidcc.ProviderConfiguration
alias Oidcc.Token

plug Oidcc.Plug.AuthorizationCallback,
[
provider: Conformance.ConfigWorker,
client_id: &Conformance.RegisterClient.client_id/0,
client_secret: &Conformance.RegisterClient.client_secret/0,
client_context_opts: &Conformance.RegisterClient.client_context_opts/0,
client_profile_opts: Conformance.RegisterClient.client_profile_opts(),
redirect_uri: &__MODULE__.redirect_url/0
]
when action in [:callback]
Expand All @@ -20,6 +24,8 @@ defmodule Conformance.AuthController do
provider: Conformance.ConfigWorker,
client_id: &Conformance.RegisterClient.client_id/0,
client_secret: &Conformance.RegisterClient.client_secret/0,
client_context_opts: &Conformance.RegisterClient.client_context_opts/0,
client_profile_opts: Conformance.RegisterClient.client_profile_opts(),
redirect_uri: &__MODULE__.redirect_url/0,
scopes: ["openid", "profile"]
]
Expand All @@ -44,50 +50,52 @@ defmodule Conformance.AuthController do
Logger.info("Retrieved Token: #{inspect(token, pretty: true)}")
Logger.info("Retrieved Userinfo: #{inspect(userinfo, pretty: true)}")

case Oidcc.ProviderConfiguration.Worker.get_provider_configuration(Conformance.ConfigWorker) do
%Oidcc.ProviderConfiguration{end_session_endpoint: :undefined} ->
conn =
with {:ok, {refreshed_token, refreshed_userinfo}} <- maybe_refresh(token) do
send_resp(
conn,
200,
inspect(
%{
token: token,
userinfo: userinfo,
refreshed_token: refreshed_token,
refreshed_userinfo: refreshed_userinfo
},
pretty: true
)
provider_configuration =
Oidcc.ProviderConfiguration.Worker.get_provider_configuration(Conformance.ConfigWorker)

{:ok, client_context} =
ClientContext.from_configuration_worker(
Conformance.ConfigWorker,
Conformance.RegisterClient.client_id(),
Conformance.RegisterClient.client_secret(),
Conformance.RegisterClient.client_context_opts()
)

conn =
with {:ok, {refreshed_token, refreshed_userinfo}} <-
maybe_refresh(token, provider_configuration),
{:ok, accounts_response} <- maybe_call_accounts(token, client_context) do
Logger.info("Refreshed Token: #{inspect(refreshed_token, pretty: true)}")
Logger.info("Refreshed Userinfo: #{inspect(refreshed_userinfo, pretty: true)}")
Logger.info("Accounts Response: #{inspect(accounts_response, pretty: true)}")

if is_binary(provider_configuration.end_session_endpoint) do
target_uri = url(~p"/logged-out")

{:ok, redirect_uri} =
Oidcc.initiate_logout_url(
token,
Conformance.ConfigWorker,
Conformance.RegisterClient.client_id(),
%{post_logout_redirect_uri: target_uri, state: "example_state"}
)
else
{:error, reason} -> error_response(conn, reason)
end

spawn(fn ->
Process.sleep(2_000)
redirect(conn, external: IO.iodata_to_binary(redirect_uri))
else
send_resp(conn, 200, "OK")
end
else
{:error, reason} -> error_response(conn, reason)
end

Conformance.Screenshot.take()
Process.send(Conformance.Runner, :stop, [])
end)

conn

%Oidcc.ProviderConfiguration{} ->
target_uri = url(~p"/logged-out")
spawn(fn ->
Process.sleep(2_000)

{:ok, redirect_uri} =
Oidcc.initiate_logout_url(
token,
Conformance.ConfigWorker,
Conformance.RegisterClient.client_id(),
Conformance.RegisterClient.client_secret(),
%{post_logout_redirect_uri: target_uri, state: "example_state"}
)
Conformance.Screenshot.take()
Process.send(Conformance.Runner, :stop, [])
end)

redirect(conn, external: IO.iodata_to_binary(redirect_uri))
end
conn
end

def callback(
Expand Down Expand Up @@ -131,30 +139,62 @@ defmodule Conformance.AuthController do
send_resp(conn, 200, inspect(%{params: params}, pretty: true))
end

defp maybe_refresh(%Token{refresh: %Token.Refresh{token: _refresh_token}} = token) do
with {:ok, token} <-
Oidcc.refresh_token(
token,
Conformance.ConfigWorker,
Conformance.RegisterClient.client_id(),
Conformance.RegisterClient.client_secret()
),
{:ok, userinfo} <-
Oidcc.retrieve_userinfo(
token,
Conformance.ConfigWorker,
Conformance.RegisterClient.client_id(),
Conformance.RegisterClient.client_secret(),
%{}
) do
Logger.info("Retrieved Token: #{inspect(token, pretty: true)}")
Logger.info("Retrieved Userinfo: #{inspect(userinfo, pretty: true)}")

{:ok, {token, userinfo}}
defp maybe_refresh(
%Token{refresh: %Token.Refresh{token: _refresh_token}} = token,
%ProviderConfiguration{grant_types_supported: grant_types_supported}
) do
if "refresh_token" in grant_types_supported do
with {:ok, token} <-
Oidcc.refresh_token(
token,
Conformance.ConfigWorker,
Conformance.RegisterClient.client_id(),
Conformance.RegisterClient.client_secret()
),
{:ok, userinfo} <-
Oidcc.retrieve_userinfo(
token,
Conformance.ConfigWorker,
Conformance.RegisterClient.client_id(),
Conformance.RegisterClient.client_secret(),
%{}
) do
Logger.info("Retrieved Token: #{inspect(token, pretty: true)}")
Logger.info("Retrieved Userinfo: #{inspect(userinfo, pretty: true)}")

{:ok, {token, userinfo}}
end
else
{:ok, {nil, nil}}
end
end

defp maybe_refresh(%Token{}), do: {:ok, {nil, nil}}
defp maybe_refresh(%Token{}, _config), do: {:ok, {nil, nil}}

defp maybe_call_accounts(token, client_context) do
accounts_uri = Application.get_env(:conformance, :call_accounts, false)

if accounts_uri do
headers =
:oidcc_auth_util.add_authorization_header(
token.access.token,
token.access.type,
:get,
accounts_uri,
%{},
ClientContext.struct_to_record(client_context)
)

:oidcc_http_util.request(
:get,
{accounts_uri, headers},
%{topic: [:conformance, :accounts]},
%{}
)
else
{:ok, nil}
end
end

defp error_response(conn, reason) do
Logger.error("OIDC Error: #{inspect(reason, pretty: true)}")
Expand Down
8 changes: 4 additions & 4 deletions lib/conformance/endpoint.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ defmodule Conformance.Endpoint do

plug(Conformance.Router)

@impl Phoenix.Endpoint
def init(_context, config) do
%URI{host: host, port: port, scheme: scheme} =
URI.new!(Ngrok.public_url(Conformance.Ngrok))
# %URI{host: host, port: port, scheme: scheme} =
# URI.new!(Ngrok.public_url(Conformance.Ngrok))

{:ok, Keyword.put(config, :url, path: "/", host: host, port: port, scheme: scheme)}
# {:ok, Keyword.put(config, :url, path: "/", host: host, port: port, scheme: scheme)}
{:ok, config}
end
end
10 changes: 9 additions & 1 deletion lib/conformance/log_configuration.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ defmodule Conformance.LogConfiguration do
ref =
:telemetry_test.attach_event_handlers(self(), [
[:oidcc, :load_configuration, :stop],
[:oidcc, :load_jwks, :stop]
[:oidcc, :load_jwks, :stop],
[:oidcc, :par_request, :start],
[:oidcc, :par_request, :stop],
[:oidcc, :par_request, :exception]
])

{:ok, ref}
Expand Down Expand Up @@ -40,4 +43,9 @@ defmodule Conformance.LogConfiguration do

{:noreply, ref}
end

def handle_info({[:oidcc | _topic], ref, _measurement, _meta} = event, ref) do
Logger.info("Event Received: #{inspect(event, pretty: true)}")
{:noreply, ref}
end
end
Loading

0 comments on commit f3c7735

Please sign in to comment.