Current section

44 Versions

Jump to

Compare versions

67 files changed
+3092 additions
-1236 deletions
  @@ -5,6 +5,39 @@ All notable changes to this project will be documented in this file.
5 5 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 6 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) according to OAuth / OpenID connect specifications, changes may break in order to comply with those.
7 7
8 + ## [3.0.0-beta.4] - 2025-07-05
9 +
10 + ### Added
11 +
12 + - support for oid4vci tx codes
13 + - oauth token is returned in credential responses
14 + - expose previous code in oauth tokens schema
15 + - accept JWT typed oid4vci proofs
16 + - signatures interface and adapters
17 + - better errors on direct post requests
18 + - verifiable credentials nested claims management
19 + - better jwt_vc presentation support
20 + - agent_credentials and agent_code flows
21 + - check presentation against public client id
22 + - better direct post success responses
23 + - authorization code grant in credential issuance
24 +
25 +
26 + ### Fixed
27 +
28 + - support for EdDSA signature algorithm
29 + - sd jwt credentials claims
30 + - clients did storage
31 + - revoke public client cache on update
32 + - presentations with public client
33 + - empty code challenges
34 +
35 + ### Security
36 +
37 + - revoke code on direct post success
38 + - status tokens chains
39 + - validate presentation resource owner if not public
40 +
8 41 ## [3.0.0-beta.3] - 2024-11-21
9 42
10 43 ### Changed
  @@ -59,7 +59,7 @@ It is a work in progress, all feedbacks / feature requests / improvements are we
59 59
60 60 ## Code of Conduct
61 61
62 - This product community follows the code of conduct available [here](https://io.malach.it/code-of-conduct.html)
62 + This product community follows the code of conduct available [here](CODE_OF_CONDUCT.md)
63 63
64 64 ## License
  @@ -33,6 +33,8 @@
33 33 <<"lib/boruta/oauth/requests/authorization_code_request.ex">>,
34 34 <<"lib/boruta/oauth/requests/hybrid_request.ex">>,
35 35 <<"lib/boruta/oauth/requests/revoke_request.ex">>,
36 + <<"lib/boruta/oauth/requests/agent_credentials_request.ex">>,
37 + <<"lib/boruta/oauth/requests/agent_code_request.ex">>,
36 38 <<"lib/boruta/oauth/requests/client_credentials_request.ex">>,
37 39 <<"lib/boruta/oauth/requests/presentation_request.ex">>,
38 40 <<"lib/boruta/oauth/requests/introspect_request.ex">>,
  @@ -45,10 +47,12 @@
45 47 <<"lib/boruta/oauth/responses/token.ex">>,
46 48 <<"lib/boruta/oauth/authorization">>,
47 49 <<"lib/boruta/oauth/authorization/client.ex">>,
50 + <<"lib/boruta/oauth/authorization/data.ex">>,
48 51 <<"lib/boruta/oauth/authorization/nonce.ex">>,
49 52 <<"lib/boruta/oauth/authorization/resource_owner.ex">>,
50 53 <<"lib/boruta/oauth/authorization/scope.ex">>,
51 54 <<"lib/boruta/oauth/authorization/code.ex">>,
55 + <<"lib/boruta/oauth/authorization/agent_token.ex">>,
52 56 <<"lib/boruta/oauth/authorization/access_token.ex">>,
53 57 <<"lib/boruta/oauth/authorization.ex">>,
54 58 <<"lib/boruta/oauth/bearer_token.ex">>,<<"lib/boruta/oauth/error.ex">>,
  @@ -60,6 +64,8 @@
60 64 <<"lib/boruta/oauth/contexts/access_tokens.ex">>,
61 65 <<"lib/boruta/oauth/contexts/requests.ex">>,
62 66 <<"lib/boruta/oauth/contexts/preauthorized_codes.ex">>,
67 + <<"lib/boruta/oauth/contexts/agent_tokens.ex">>,
68 + <<"lib/boruta/oauth/contexts/signatures.ex">>,
63 69 <<"lib/boruta/oauth/revoke.ex">>,<<"lib/boruta/oauth/application.ex">>,
64 70 <<"lib/boruta/oauth/request.ex">>,<<"lib/boruta/openid">>,
65 71 <<"lib/boruta/openid/json">>,<<"lib/boruta/openid/json/schema.ex">>,
  @@ -76,15 +82,25 @@
76 82 <<"lib/boruta/openid/responses/verifiable_presentation.ex">>,
77 83 <<"lib/boruta/openid/responses/credential.ex">>,
78 84 <<"lib/boruta/openid/responses/siopv2.ex">>,
85 + <<"lib/boruta/openid/responses/direct_post.ex">>,
79 86 <<"lib/boruta/openid/responses/userinfo.ex">>,
80 87 <<"lib/boruta/openid/responses/defered_credential.ex">>,
88 + <<"lib/boruta/openid/verifiable_presentations.ex">>,
81 89 <<"lib/boruta/openid/contexts">>,
82 90 <<"lib/boruta/openid/contexts/clients.ex">>,
91 + <<"lib/boruta/openid/contexts/signatures.ex">>,
83 92 <<"lib/boruta/openid/contexts/credentials.ex">>,
84 - <<"lib/boruta/openid/application.ex">>,<<"lib/boruta/openid.ex">>,
85 - <<"lib/boruta/adapters">>,<<"lib/boruta/adapters/codes.ex">>,
86 - <<"lib/boruta/adapters/clients.ex">>,<<"lib/boruta/adapters/scopes.ex">>,
87 - <<"lib/boruta/adapters/ecto">>,<<"lib/boruta/adapters/ecto/errors.ex">>,
93 + <<"lib/boruta/openid/application.ex">>,
94 + <<"lib/boruta/openid/verifiable_credentials.ex">>,
95 + <<"lib/boruta/openid.ex">>,<<"lib/boruta/adapters">>,
96 + <<"lib/boruta/adapters/token_generator.ex">>,
97 + <<"lib/boruta/adapters/codes.ex">>,<<"lib/boruta/adapters/clients.ex">>,
98 + <<"lib/boruta/adapters/universal">>,
99 + <<"lib/boruta/adapters/universal/signatures">>,
100 + <<"lib/boruta/adapters/universal/signatures/signing_key.ex">>,
101 + <<"lib/boruta/adapters/universal/signatures.ex">>,
102 + <<"lib/boruta/adapters/scopes.ex">>,<<"lib/boruta/adapters/ecto">>,
103 + <<"lib/boruta/adapters/ecto/errors.ex">>,
88 104 <<"lib/boruta/adapters/ecto/codes.ex">>,
89 105 <<"lib/boruta/adapters/ecto/clients.ex">>,
90 106 <<"lib/boruta/adapters/ecto/schemas">>,
  @@ -102,6 +118,7 @@
102 118 <<"lib/boruta/adapters/ecto/requests.ex">>,
103 119 <<"lib/boruta/adapters/ecto/preauthorized_codes.ex">>,
104 120 <<"lib/boruta/adapters/ecto/admin.ex">>,
121 + <<"lib/boruta/adapters/ecto/agent_tokens.ex">>,
105 122 <<"lib/boruta/adapters/ecto/oauth_mapper.ex">>,
106 123 <<"lib/boruta/adapters/ecto/credentials.ex">>,
107 124 <<"lib/boruta/adapters/ecto/stores">>,
  @@ -111,13 +128,15 @@
111 128 <<"lib/boruta/adapters/access_tokens.ex">>,
112 129 <<"lib/boruta/adapters/requests.ex">>,
113 130 <<"lib/boruta/adapters/preauthorized_codes.ex">>,
114 - <<"lib/boruta/adapters/credentials.ex">>,
115 - <<"lib/boruta/verifiable_presentations.ex">>,<<"lib/boruta/did.ex">>,
131 + <<"lib/boruta/adapters/agent_tokens.ex">>,
132 + <<"lib/boruta/adapters/internal">>,
133 + <<"lib/boruta/adapters/internal/signatures">>,
134 + <<"lib/boruta/adapters/internal/signatures/signing_key.ex">>,
135 + <<"lib/boruta/adapters/internal/signatures.ex">>,
136 + <<"lib/boruta/adapters/credentials.ex">>,<<"lib/boruta/did.ex">>,
116 137 <<"lib/boruta/cache.ex">>,<<"lib/boruta/oauth.ex">>,
117 138 <<"lib/boruta/application.ex">>,<<"lib/boruta/repo.ex">>,
118 - <<"lib/boruta/config.ex">>,<<"lib/boruta/dpop.ex">>,
119 - <<"lib/boruta/verifiable_credentials.ex">>,<<"lib/boruta/utils">>,
120 - <<"lib/boruta/utils/token_generator.ex">>,
139 + <<"lib/boruta/config.ex">>,<<"lib/boruta/dpop.ex">>,<<"lib/boruta/utils">>,
121 140 <<"lib/boruta/utils/basic_auth.ex">>,<<"lib/boruta.ex">>,<<"lib/mix">>,
122 141 <<"lib/mix/tasks">>,<<"lib/mix/tasks/boruta.gen.controllers.ex">>,
123 142 <<"lib/mix/tasks/boruta.gen.migration.ex">>,<<"lib/ex_json_schema">>,
  @@ -128,6 +147,7 @@
128 147 <<"priv/boruta/migrations/20220625210731_confidential_clients.ex">>,
129 148 <<"priv/boruta/migrations/20240824202945_clients_did.ex">>,
130 149 <<"priv/boruta/migrations/20210824001622_create_boruta.ex">>,
150 + <<"priv/boruta/migrations/20250315093643_fix_oauth_clients_did.ex">>,
131 151 <<"priv/boruta/migrations/20210916124216_clients_refresh_tokens.ex">>,
132 152 <<"priv/boruta/migrations/20240127084350_siopv2_implementation.ex">>,
133 153 <<"priv/boruta/migrations/20211010220831_clients_public_revoke.ex">>,
  @@ -136,16 +156,20 @@
136 156 <<"priv/boruta/migrations/20240416065621_par_implementation.ex">>,
137 157 <<"priv/boruta/migrations/20231217154004_oid4vci_implementation.ex">>,
138 158 <<"priv/boruta/migrations/20220603191707_id_token_signature_alg_configuration.ex">>,
159 + <<"priv/boruta/migrations/20250524180254_public_client_id.ex">>,
160 + <<"priv/boruta/migrations/20241209115239_tokens_tx_code.ex">>,
139 161 <<"priv/boruta/migrations/20241021151746_clients_key_pair_types.ex">>,
140 162 <<"priv/boruta/migrations/20221129125812_signed_userinfo_response.ex">>,
141 163 <<"priv/boruta/migrations/20230524132504_optional_public_key_for_oauth_clients.ex">>,
142 164 <<"priv/boruta/migrations/20230727181622_add_metadata_to_clients.ex">>,
143 165 <<"priv/boruta/migrations/20240506100327_c_nonce_implementation.ex">>,
166 + <<"priv/boruta/migrations/20241221231456_agent_credentials.ex">>,
144 167 <<"priv/boruta/migrations/20230514152712_clients_jwks_uri.ex">>,
145 168 <<"priv/boruta/migrations/20240908101238_verifiable_presentation_definitions.ex">>,
146 169 <<"priv/boruta/migrations/20221122140935_client_authentication_methods.ex">>,
147 170 <<"priv/boruta/migrations/20221009122204_authorization_code_chains.ex">>,
148 171 <<"priv/boruta/migrations/20240812131753_defered_credentials.ex">>,
172 + <<"priv/boruta/migrations/20241220105748_clients_signatures_adapters.ex">>,
149 173 <<"priv/boruta/migrations/20240320140543_dpop_implementation.ex">>,
150 174 <<"priv/boruta/migrations/20220822204634_refresh_token_rotation.ex">>,
151 175 <<"priv/boruta/migrations/20220109171634_store_previous_token.ex">>,
  @@ -169,19 +193,26 @@
169 193 <<"priv/repo/migrations/20230515150324_add_id_token_kid_to_clients.exs">>,
170 194 <<"priv/repo/migrations/20210904185118_add_public_refresh_token_to_clients.exs">>,
171 195 <<"priv/repo/migrations/20210720134116_add_default_to_scopes_name.exs">>,
196 + <<"priv/repo/migrations/20250315083414_change_oauth_clients_did_to_text.exs">>,
172 197 <<"priv/repo/migrations/20230514122748_add_jwks_uri_to_clients.exs">>,
173 198 <<"priv/repo/migrations/20241021114643_add_key_pair_type_to_oauth_clients.exs">>,
199 + <<"priv/repo/migrations/20241221232600_add_agent_token_to_oauth_tokens.exs">>,
174 200 <<"priv/repo/migrations/20220109161041_add_previous_token_to_oauth_tokens.exs">>,
175 201 <<"priv/repo/migrations/20240506073706_add_c_nonce_to_oauth_tokens.exs">>,
202 + <<"priv/repo/migrations/20241221205452_add_bind_data_to_oauth_tokens.exs">>,
203 + <<"priv/repo/migrations/20250524142111_add_public_client_id_to_oauth_tokens.exs">>,
176 204 <<"priv/repo/migrations/20221121100117_add_token_endpoint_jwt_auth_alg.exs">>,
177 205 <<"priv/repo/migrations/20240824181826_add_did_to_oauth_clients.exs">>,
206 + <<"priv/repo/migrations/20241220082127_add_signatures_adapter_to_oauth_clients.exs">>,
178 207 <<"priv/repo/migrations/20210926205845_add_revoke_and_introspect_to_clients_supported_grant_types.exs">>,
179 208 <<"priv/repo/migrations/20210721213916_add_nonce_to_tokens.exs">>,
180 209 <<"priv/repo/migrations/20200218193706_add_supported_grant_types_to_clients.exs">>,
181 210 <<"priv/repo/migrations/20191101112745_change_redirect_uri_to_redirect_uris.exs">>,
211 + <<"priv/repo/migrations/20241209092043_add_tx_code_to_tokens.exs">>,
182 212 <<"priv/repo/migrations/20210114202055_usec_timestamps.exs">>,
183 213 <<"priv/repo/migrations/20201129013217_add_access_token_ttl_to_clients.exs">>,
184 214 <<"priv/repo/migrations/20240228103215_change_oauth_token_sub.exs">>,
215 + <<"priv/repo/migrations/20241226184245_modify_oauth_clients_did.exs">>,
185 216 <<"priv/repo/migrations/20210720134125_add_default_to_tokens_scope.exs">>,
186 217 <<"priv/repo/migrations/20210914115259_add_refresh_token_ttl_to_clients.exs">>,
187 218 <<"priv/repo/migrations/20240126125129_insert_public_client.exs">>,
  @@ -249,7 +280,8 @@
249 280 {<<"name">>,<<"owl">>},
250 281 {<<"optional">>,false},
251 282 {<<"repository">>,<<"hexpm">>},
252 - {<<"requirement">>,<<"~> 0.8.0">>}],
283 + {<<"requirement">>,
284 + <<"~> 0.8.0 or ~> 0.9.0 or ~> 0.10.0 or ~> 0.11.0 or ~> 0.12.0">>}],
253 285 [{<<"app">>,<<"jason">>},
254 286 {<<"name">>,<<"jason">>},
255 287 {<<"optional">>,false},
  @@ -300,4 +332,4 @@
300 332 {<<"optional">>,false},
301 333 {<<"repository">>,<<"hexpm">>},
302 334 {<<"requirement">>,<<"~> 1.0">>}]]}.
303 - {<<"version">>,<<"3.0.0-beta.3">>}.
335 + {<<"version">>,<<"3.0.0-beta.4">>}.
  @@ -0,0 +1,15 @@
1 + defmodule Boruta.AgentTokensAdapter do
2 + @moduledoc """
3 + Encapsulate injected `Boruta.Oauth.AgentTokens` adapter in context configuration
4 + """
5 +
6 + @behaviour Boruta.Oauth.AgentTokens
7 +
8 + import Boruta.Config, only: [agent_tokens: 0]
9 +
10 + def get_by(params), do: agent_tokens().get_by(params)
11 + def create(params, opts), do: agent_tokens().create(params, opts)
12 + def revoke(token), do: agent_tokens().revoke(token)
13 + def revoke_refresh_token(token), do: agent_tokens().revoke_refresh_token(token)
14 + def claims_from_agent_token(token), do: agent_tokens().claims_from_agent_token(token)
15 + end
  @@ -58,6 +58,7 @@ defmodule Boruta.Ecto.AccessTokens do
58 58 previous_token = params[:previous_token]
59 59 previous_code = params[:previous_code]
60 60 resource_owner = params[:resource_owner]
61 + agent_token = params[:agent_token]
61 62
62 63 authorization_details =
63 64 params[:authorization_details] || (resource_owner && resource_owner.authorization_details)
  @@ -71,7 +72,8 @@ defmodule Boruta.Ecto.AccessTokens do
71 72 access_token_ttl: access_token_ttl,
72 73 previous_token: previous_token,
73 74 previous_code: previous_code,
74 - authorization_details: authorization_details
75 + authorization_details: authorization_details,
76 + agent_token: agent_token
75 77 }
76 78
77 79 changeset =
Loading more files…