Skip to content

Commit

Permalink
Do not crash when userinfo endpoint is not implemented by the issuer
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewDryga committed Apr 24, 2024
1 parent d743020 commit c3ab295
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 1 deletion.
2 changes: 2 additions & 0 deletions lib/openid_connect.ex
Original file line number Diff line number Diff line change
Expand Up @@ -314,13 +314,15 @@ defmodule OpenIDConnect do
headers = [{"Authorization", "Bearer #{access_token}"}]

with {:ok, document} <- Document.fetch_document(discovery_document_uri),
true <- not is_nil(document.userinfo_endpoint),
request = Finch.build(:get, document.userinfo_endpoint, headers),
{:ok, %Finch.Response{body: response, status: status}} when status in 200..299 <-
Finch.request(request, OpenIDConnect.Finch),
{:ok, json} <- Jason.decode(response) do
{:ok, json}
else
{:ok, %Finch.Response{body: response, status: status}} -> {:error, {status, response}}
false -> {:error, :userinfo_endpoint_is_not_implemented}
other -> other
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/openid_connect/document.ex
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ defmodule OpenIDConnect.Document do
authorization_endpoint: Map.fetch!(document_json, "authorization_endpoint"),
end_session_endpoint: Map.get(document_json, "end_session_endpoint"),
token_endpoint: Map.fetch!(document_json, "token_endpoint"),
userinfo_endpoint: Map.fetch!(document_json, "userinfo_endpoint"),
userinfo_endpoint: Map.get(document_json, "userinfo_endpoint"),
response_types_supported:
Map.get(document_json, "response_types_supported")
|> Enum.map(fn response_type ->
Expand Down
23 changes: 23 additions & 0 deletions test/openid_connect_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,29 @@ defmodule OpenIDConnectTest do
assert {"authorization", "Bearer #{token}"} in headers
end

test "returns error when userinfo endpoint is not defined by discovery document" do
{jwks, []} = Code.eval_file("test/fixtures/jwks/jwk.exs")
jwk = JOSE.JWK.from(jwks)
{_, jwk_pubkey} = JOSE.JWK.to_public_map(jwk)

{_bypass, uri} =
start_fixture("vault", %{
"jwks" => jwk_pubkey,
"userinfo_endpoint" => nil
})

config = %{@config | discovery_document_uri: uri}

claims = %{"email" => "[email protected]"}

{_alg, token} =
jwk
|> JOSE.JWS.sign(Jason.encode!(claims), %{"alg" => "RS256"})
|> JOSE.JWS.compact()

assert fetch_userinfo(config, token) == {:error, :userinfo_endpoint_is_not_implemented}
end

test "returns error when userinfo endpoint is not available" do
bypass = Bypass.open()
userinfo_endpoint = "http://localhost:#{bypass.port}/userinfo"
Expand Down

0 comments on commit c3ab295

Please sign in to comment.