diff --git a/include/oidcc_client_context.hrl b/include/oidcc_client_context.hrl index 154a00b..7c2bd65 100644 --- a/include/oidcc_client_context.hrl +++ b/include/oidcc_client_context.hrl @@ -4,7 +4,7 @@ provider_configuration :: oidcc_provider_configuration:t(), jwks :: jose_jwk:key(), client_id :: binary(), - client_secret :: binary(), + client_secret :: binary() | unauthenticated, client_jwks = none :: jose_jwk:key() | none }). diff --git a/lib/oidcc.ex b/lib/oidcc.ex index 93b08eb..cf95c38 100644 --- a/lib/oidcc.ex +++ b/lib/oidcc.ex @@ -371,8 +371,7 @@ defmodule Oidcc do ...> {:ok, _redirect_uri} = Oidcc.initiate_logout_url( ...> token, ...> pid, - ...> "client_id", - ...> "client_secret" + ...> "client_id" ...> ) """ @@ -381,7 +380,6 @@ defmodule Oidcc do token :: id_token | Oidcc.Token.t() | :undefined, provider_configuration_name :: GenServer.name(), client_id :: String.t(), - client_secret :: String.t(), opts :: :oidcc_logout.initiate_url_opts() | :oidcc_client_context.opts() ) :: {:ok, :uri_string.uri_string()} @@ -391,7 +389,6 @@ defmodule Oidcc do token, provider_configuration_name, client_id, - client_secret, opts \\ %{} ) do token = @@ -405,7 +402,6 @@ defmodule Oidcc do token, provider_configuration_name, client_id, - client_secret, opts ) end diff --git a/lib/oidcc/client_context.ex b/lib/oidcc/client_context.ex index 82cda23..a4a4bfa 100644 --- a/lib/oidcc/client_context.ex +++ b/lib/oidcc/client_context.ex @@ -17,7 +17,10 @@ defmodule Oidcc.ClientContext do alias Oidcc.ProviderConfiguration @typedoc since: "3.0.0" - @type t() :: %__MODULE__{ + @type t() :: authenticated_t() | unauthenticated_t() + + @typedoc since: "3.0.0" + @type authenticated_t() :: %__MODULE__{ provider_configuration: ProviderConfiguration.t(), jwks: JOSE.JWK.t(), client_id: String.t(), @@ -25,6 +28,15 @@ defmodule Oidcc.ClientContext do client_jwks: JOSE.JWK.t() | none } + @typedoc since: "3.0.0" + @type unauthenticated_t() :: %__MODULE__{ + provider_configuration: ProviderConfiguration.t(), + jwks: JOSE.JWK.t(), + client_id: String.t(), + client_secret: :unauthenticated, + client_jwks: :none + } + @doc """ Create Client Context from a `Oidcc.ProviderConfiguration.Worker` @@ -56,8 +68,14 @@ defmodule Oidcc.ClientContext do provider_name :: GenServer.name(), client_id :: String.t(), client_secret :: String.t(), - opts :: :oidcc_client_context.opts() - ) :: {:ok, t()} | {:error, :oidcc_client_context.t()} + opts :: :oidcc_client_context.authenticated_opts() + ) :: {:ok, authenticated_t()} | {:error, :oidcc_client_context.t()} + @spec from_configuration_worker( + provider_name :: GenServer.name(), + client_id :: String.t(), + client_secret :: :unauthenticated, + opts :: :oidcc_client_context.unauthenticated_opts() + ) :: {:ok, unauthenticated_t()} | {:error, :oidcc_client_context.t()} def from_configuration_worker(provider_name, client_id, client_secret, opts \\ %{}) do opts = Map.update(opts, :client_jwks, :none, &JOSE.JWK.to_record/1) @@ -102,8 +120,15 @@ defmodule Oidcc.ClientContext do jwks :: JOSE.JWK.t(), client_id :: String.t(), client_secret :: String.t(), - opts :: :oidcc_client_context.opts() - ) :: t() + opts :: :oidcc_client_context.authenticated_opts() + ) :: authenticated_t() + @spec from_manual( + configuration :: ProviderConfiguration.t(), + jwks :: JOSE.JWK.t(), + client_id :: String.t(), + client_secret :: :unauthenticated, + opts :: :oidcc_client_context.unauthenticated_opts() + ) :: unauthenticated_t() def from_manual(configuration, jwks, client_id, client_secret, opts \\ %{}) do configuration = ProviderConfiguration.struct_to_record(configuration) jwks = JOSE.JWK.to_record(jwks) diff --git a/lib/oidcc/logout.ex b/lib/oidcc/logout.ex index ed9464d..b1ba89e 100644 --- a/lib/oidcc/logout.ex +++ b/lib/oidcc/logout.ex @@ -12,7 +12,7 @@ defmodule Oidcc.Logout do See https://openid.net/specs/openid-connect-rpinitiated-1_0.html#RPLogout For a high level interface using `Oidcc.ProviderConfiguration.Worker` - see `Oidcc.initiate_logout_url/5`. + see `Oidcc.initiate_logout_url/4`. ## Examples @@ -25,7 +25,7 @@ defmodule Oidcc.Logout do ...> Oidcc.ClientContext.from_configuration_worker( ...> pid, ...> "client_id", - ...> "client_secret" + ...> :unauthenticated ...> ) ...> ...> # Get `token` from `Oidcc.retrieve_token/5` diff --git a/src/oidcc.erl b/src/oidcc.erl index aa2f2ce..50c8719 100644 --- a/src/oidcc.erl +++ b/src/oidcc.erl @@ -30,7 +30,7 @@ -export([client_credentials_token/4]). -export([create_redirect_url/4]). --export([initiate_logout_url/5]). +-export([initiate_logout_url/4]). -export([introspect_token/5]). -export([jwt_profile_token/6]). -export([refresh_token/5]). @@ -65,7 +65,7 @@ when ProviderConfigurationWorkerName :: gen_server:server_ref(), ClientId :: binary(), - ClientSecret :: binary(), + ClientSecret :: binary() | unauthenticated, Opts :: oidcc_authorization:opts() | oidcc_client_context:opts(), Uri :: uri_string:uri_string(). create_redirect_url(ProviderConfigurationWorkerName, ClientId, ClientSecret, Opts) -> @@ -108,7 +108,7 @@ create_redirect_url(ProviderConfigurationWorkerName, ClientId, ClientSecret, Opt AuthCode, ProviderConfigurationWorkerName, ClientId, - ClientSecret, + ClientSecret | unauthenticated, Opts ) -> {ok, oidcc_token:t()} | {error, oidcc_client_context:error() | oidcc_token:error()} @@ -165,7 +165,7 @@ retrieve_token( Token, ProviderConfigurationWorkerName, ClientId, - ClientSecret, + ClientSecret | unauthenticated, Opts ) -> {ok, map()} | {error, oidcc_client_context:error() | oidcc_userinfo:error()} @@ -173,7 +173,7 @@ retrieve_token( Token :: oidcc_token:t(), ProviderConfigurationWorkerName :: gen_server:server_ref(), ClientId :: binary(), - ClientSecret :: binary(), + ClientSecret :: binary() | unauthenticated, Opts :: oidcc_userinfo:retrieve_opts_no_sub() | oidcc_client_context:opts(); (Token, ProviderConfigurationWorkerName, ClientId, ClientSecret, Opts) -> {ok, map()} | {error, any()} @@ -226,7 +226,7 @@ retrieve_userinfo( RefreshToken, ProviderConfigurationWorkerName, ClientId, - ClientSecret, + ClientSecret | unauthenticated, Opts ) -> {ok, oidcc_token:t()} | {error, oidcc_client_context:error() | oidcc_token:error()} @@ -357,7 +357,7 @@ introspect_token( Subject, ProviderConfigurationWorkerName, ClientId, - ClientSecret, + ClientSecret | unauthenticated, Jwk, Opts ) -> {ok, oidcc_token:t()} | {error, oidcc_client_context:error() | oidcc_token:error()} when @@ -443,7 +443,6 @@ client_credentials_token(ProviderConfigurationWorkerName, ClientId, ClientSecret %% Token, %% provider_name, %% <<"client_id">>, -%% <<"client_secret">>, %% #{post_logout_redirect_uri: <<"https://my.server/return"} %% ), %% @@ -455,7 +454,6 @@ client_credentials_token(ProviderConfigurationWorkerName, ClientId, ClientSecret Token, ProviderConfigurationWorkerName, ClientId, - ClientSecret, Opts ) -> {ok, uri_string:uri_string()} | {error, oidcc_client_context:error() | oidcc_logout:error()} @@ -464,9 +462,8 @@ when IdToken :: binary(), ProviderConfigurationWorkerName :: gen_server:server_ref(), ClientId :: binary(), - ClientSecret :: binary(), - Opts :: oidcc_logout:initiate_url_opts() | oidcc_client_context:opts(). -initiate_logout_url(Token, ProviderConfigurationWorkerName, ClientId, ClientSecret, Opts) -> + Opts :: oidcc_logout:initiate_url_opts() | oidcc_client_context:unauthenticated_opts(). +initiate_logout_url(Token, ProviderConfigurationWorkerName, ClientId, Opts) -> {ClientContextOpts, OtherOpts} = extract_client_context_opts(Opts), maybe @@ -474,7 +471,7 @@ initiate_logout_url(Token, ProviderConfigurationWorkerName, ClientId, ClientSecr oidcc_client_context:from_configuration_worker( ProviderConfigurationWorkerName, ClientId, - ClientSecret, + unauthenticated, ClientContextOpts ), oidcc_logout:initiate_url(Token, ClientContext, OtherOpts) diff --git a/src/oidcc_authorization.erl b/src/oidcc_authorization.erl index 318cb43..9aa4374 100644 --- a/src/oidcc_authorization.erl +++ b/src/oidcc_authorization.erl @@ -167,6 +167,8 @@ attempt_request_object(QueryParams, #oidcc_client_context{ provider_configuration = #oidcc_provider_configuration{request_parameter_supported = false} }) -> QueryParams; +attempt_request_object(QueryParams, #oidcc_client_context{client_secret = unauthenticated}) -> + QueryParams; attempt_request_object(QueryParams, #oidcc_client_context{ client_id = ClientId, client_secret = ClientSecret, diff --git a/src/oidcc_client_context.erl b/src/oidcc_client_context.erl index 0b49722..225f389 100644 --- a/src/oidcc_client_context.erl +++ b/src/oidcc_client_context.erl @@ -22,27 +22,43 @@ -include_lib("jose/include/jose_jwk.hrl"). +-export_type([authenticated_opts/0]). +-export_type([authenticated_t/0]). -export_type([error/0]). -export_type([opts/0]). -export_type([t/0]). +-export_type([unauthenticated_opts/0]). +-export_type([unauthenticated_t/0]). -export([from_configuration_worker/3]). -export([from_configuration_worker/4]). -export([from_manual/4]). -export([from_manual/5]). --type t() :: - #oidcc_client_context{ - provider_configuration :: oidcc_provider_configuration:t(), - jwks :: jose_jwk:key(), - client_id :: binary(), - client_secret :: binary(), - client_jwks :: jose_jwk:key() | none - }. +-type t() :: authenticated_t() | unauthenticated_t(). --type opts() :: #{ +-type authenticated_t() :: #oidcc_client_context{ + provider_configuration :: oidcc_provider_configuration:t(), + jwks :: jose_jwk:key(), + client_id :: binary(), + client_secret :: binary(), + client_jwks :: jose_jwk:key() | none +}. + +-type unauthenticated_t() :: #oidcc_client_context{ + provider_configuration :: oidcc_provider_configuration:t(), + jwks :: jose_jwk:key(), + client_id :: binary(), + client_secret :: unauthenticated, + client_jwks :: none +}. + +-type authenticated_opts() :: #{ client_jwks => jose_jwk:key() }. +-type unauthenticated_opts() :: #{}. + +-type opts() :: authenticated_opts() | unauthenticated_opts(). -type error() :: provider_not_ready. @@ -51,12 +67,15 @@ %% See {@link from_configuration_worker/4} %% @end %% @since 3.0.0 --spec from_configuration_worker(ProviderName, ClientId, ClientSecret) -> - {ok, t()} | {error, error()} -when - ProviderName :: gen_server:server_ref(), - ClientId :: binary(), - ClientSecret :: binary(). +-spec from_configuration_worker + (ProviderName, ClientId, ClientSecret) -> {ok, authenticated_t()} | {error, error()} when + ProviderName :: gen_server:server_ref(), + ClientId :: binary(), + ClientSecret :: binary(); + (ProviderName, ClientId, ClientSecret) -> {ok, unauthenticated_t()} | {error, error()} when + ProviderName :: gen_server:server_ref(), + ClientId :: binary(), + ClientSecret :: unauthenticated. from_configuration_worker(ProviderName, ClientId, ClientSecret) -> from_configuration_worker(ProviderName, ClientId, ClientSecret, #{}). @@ -93,22 +112,30 @@ from_configuration_worker(ProviderName, ClientId, ClientSecret) -> %% ''' %% @end %% @since 3.0.0 --spec from_configuration_worker(ProviderName, ClientId, ClientSecret, Opts) -> - {ok, t()} | {error, error()} -when - ProviderName :: gen_server:server_ref(), - ClientId :: binary(), - ClientSecret :: binary(), - Opts :: opts(). +-spec from_configuration_worker + (ProviderName, ClientId, ClientSecret, Opts) -> + {ok, authenticated_t()} | {error, error()} + when + ProviderName :: gen_server:server_ref(), + ClientId :: binary(), + ClientSecret :: binary(), + Opts :: authenticated_opts(); + (ProviderName, ClientId, ClientSecret, Opts) -> + {ok, unauthenticated_t()} | {error, error()} + when + ProviderName :: gen_server:server_ref(), + ClientId :: binary(), + ClientSecret :: unauthenticated, + Opts :: unauthenticated_opts(). from_configuration_worker(ProviderName, ClientId, ClientSecret, Opts) when is_pid(ProviderName) -> - {ok, #oidcc_client_context{ - provider_configuration = + {ok, + from_manual( oidcc_provider_configuration_worker:get_provider_configuration(ProviderName), - jwks = oidcc_provider_configuration_worker:get_jwks(ProviderName), - client_id = ClientId, - client_secret = ClientSecret, - client_jwks = maps:get(client_jwks, Opts, none) - }}; + oidcc_provider_configuration_worker:get_jwks(ProviderName), + ClientId, + ClientSecret, + Opts + )}; from_configuration_worker(ProviderName, ClientId, ClientSecret, Opts) -> case erlang:whereis(ProviderName) of undefined -> @@ -122,11 +149,17 @@ from_configuration_worker(ProviderName, ClientId, ClientSecret, Opts) -> %% See {@link from_manual/5} %% @end %% @since 3.0.0 --spec from_manual(Configuration, Jwks, ClientId, ClientSecret) -> t() when - Configuration :: oidcc_provider_configuration:t(), - Jwks :: jose_jwk:key(), - ClientId :: binary(), - ClientSecret :: binary(). +-spec from_manual + (Configuration, Jwks, ClientId, ClientSecret) -> authenticated_t() when + Configuration :: oidcc_provider_configuration:t(), + Jwks :: jose_jwk:key(), + ClientId :: binary(), + ClientSecret :: binary(); + (Configuration, Jwks, ClientId, ClientSecret) -> unauthenticated_t() when + Configuration :: oidcc_provider_configuration:t(), + Jwks :: jose_jwk:key(), + ClientId :: binary(), + ClientSecret :: unauthenticated. from_manual(Configuration, Jwks, ClientId, ClientSecret) -> from_manual(Configuration, Jwks, ClientId, ClientSecret, #{}). @@ -154,21 +187,39 @@ from_manual(Configuration, Jwks, ClientId, ClientSecret) -> %% ''' %% @end %% @since 3.0.0 --spec from_manual(Configuration, Jwks, ClientId, ClientSecret, Opts) -> t() when - Configuration :: oidcc_provider_configuration:t(), - Jwks :: jose_jwk:key(), - ClientId :: binary(), - ClientSecret :: binary(), - Opts :: opts(). +-spec from_manual + (Configuration, Jwks, ClientId, ClientSecret, Opts) -> authenticated_t() when + Configuration :: oidcc_provider_configuration:t(), + Jwks :: jose_jwk:key(), + ClientId :: binary(), + ClientSecret :: binary(), + Opts :: authenticated_opts(); + (Configuration, Jwks, ClientId, ClientSecret, Opts) -> unauthenticated_t() when + Configuration :: oidcc_provider_configuration:t(), + Jwks :: jose_jwk:key(), + ClientId :: binary(), + ClientSecret :: unauthenticated, + Opts :: unauthenticated_opts(). +from_manual( + #oidcc_provider_configuration{} = Configuration, + #jose_jwk{} = Jwks, + ClientId, + unauthenticated, + _Opts +) when is_binary(ClientId) -> + #oidcc_client_context{ + provider_configuration = Configuration, + jwks = Jwks, + client_id = ClientId, + client_secret = unauthenticated + }; from_manual( #oidcc_provider_configuration{} = Configuration, #jose_jwk{} = Jwks, ClientId, ClientSecret, Opts -) when - is_binary(ClientId) and is_binary(ClientSecret) --> +) when is_binary(ClientId), is_binary(ClientSecret) -> #oidcc_client_context{ provider_configuration = Configuration, jwks = Jwks, diff --git a/src/oidcc_logout.erl b/src/oidcc_logout.erl index 9d555c1..bebc51e 100644 --- a/src/oidcc_logout.erl +++ b/src/oidcc_logout.erl @@ -46,7 +46,7 @@ %% See [https://openid.net/specs/openid-connect-rpinitiated-1_0.html#RPLogout] %% %% For a high level interface using {@link oidcc_provider_configuration_worker} -%% see {@link oidcc:initiate_logout_url/5}. +%% see {@link oidcc:initiate_logout_url/4}. %% %%