The intent of this document is to make migration of breaking changes as easy as possible. Please note that not all breaking changes might be included here. Please check the CHANGELOG.md for a full list of changes before finalizing the upgrade process.
- 1.0.0-beta.8
- 1.0.0-beta.7
- 1.0.0-beta.5
- 1.0.0-beta.1
- 0.11.12
- 0.11.3
- 0.11.0
- 0.10.0
- Breaking Changes
- Important Additions
- Important Changes
- 0.9.0
- 0.8.0
This patch introduces some minor database schema changes. Before you apply it, you must run hydra migrate sql
against
your database.
Previously, OAuth 2.0 Clients had a flag called public
. If set to true, the OAuth 2.0 Client was able to exchange
authorize codes for access tokens without a password. This is useful in scenarios where the device can not keep
a secret (browser app, mobile app).
Since OpenID Connect Dynamic Discovery was added, this flag collided with the token_endpoint_auth_method
. If
token_endpoint_auth_method
is set to none
, then that is equal to setting public
to true
. To remove this
ambiguity the public
flag was removed.
If you wish to create a client that runs on an untrusted device (browser app, mobile app), simply set "token_endpoint_auth_method": "none"
in the JSON request.
If you are using the ORY Hydra CLI, you can use --token-endpoint-auth-method none
to achieve what --is-public
did
previously.
The SQL migrations will automatically migrate clients that have public
set to true
by setting token_endpoint_auth_method
to none
.
This patch resolves an issue which caused the migration to fail from beta.4 to beta.5 / beta.6. The reason being that
the keys stored in the data store had mismatching kid
values if generated by <= beta.5. This patch runs a SQL migration
script which removes the old key and then, after booting up ORY Hydra, regenerates it.
To apply this change, please run you must run hydra migrate sql
against your database.
This patch implements the OpenID Connect Dynamic Client registration specification and thus now supports client authentication via JSON Web Tokens signed with RSA public/private keypairs, alongside HTTP Basic Authorization and sending the client's ID and secret in the POST body.
For more information on this, please refer to the specification.
Previously, when response types such as code token id_token
were requested (OpenID Connect Hybrid Flow) it was enough
for the client to have response_types=["code", "token", "id_token"]
. This is however incompatible with the
OpenID Connect Dynamic Client Registration 1.0 spec which dictates that the response_types
have to match exactly.
Assuming you are requesting &response_types=code+token+id_token
, your client should have response_types=["code token id_token"]
,
if other response types are required (e.g. &response_types=code
, &response_types=token
) they too must be included:
response_types=["code", "token", "code token id_token"]
.
This will only affect you if you have clients requesting OpenID Connect Hybrid flows where more than one response_type is requested.
This patch introduces some minor database schema changes. Before you apply it, you must run hydra migrate sql
against
your database.
Previously, errors have been returned as nested objects:
{
"error": {
"error": "invalid_request"
// ...
}
}
while other endpoints, specifically those under OAuth 2.0 / OpenID Connect returned them without nesting:
{
"error": "invalid_request"
// ...
}
This patch updates all error responses and formats them coherently as across all APIs:
{
"error": "invalid_request"
// ...
}
With support for the OpenID Connect Dynamic Discovery specification, a new field has been added to the OAuth 2.0 Client's
metadata which is token_endpoint_auth_method
. The token_endpoint_auth_method
specifies which authentication methods
the client can use at the token, introspection, and revocation endpoint.
The default value for this method is client_secret_basic
which uses the Basic HTTP Authorization scheme. If your client
uses the POST body to perform authentication, this value must be changed to client_secret_post
The OpenID Connect Dynamic Client Registration 1.0 spec
formulates that the client's ID should be sent as field client_id
. Until now, the id was sent as field id
. This
release changes that. For example, what was previously
$ curl http://hydra/clients/my-client
{
"id": "my-client",
// ...
}
is now
$ curl http://hydra/clients/my-client
{
"client_id": "my-client",
// ...
}
For now, the id
field will still be returned, but is marked deprecated and will be removed in future releases.
This section summarizes important changes introduced in 1.0.0. Follow it chronologically to ensure a proper migration.
We are very well aware that the changelist is huge and we try to prepare you as good as we can to migrate to this version. We also understand that breaking changes are frustrating and it takes time to adopt to them. We sincerely hope that the benefits from this version (improved consent flow, easier set up, clear boundaries & responsibilities) outweigh the hassle of upgrading to the new version.
If you have difficulties upgrading and would like a helping hand, reach out to us at mailto:[email protected] and we will help you with the upgrade process. Our services are billed by the hour and are priced fairly.
This is a (potentially incomplete) summary of what needs to be done to upgrade from versions of the 0.9.x branch, which are still common. As always, try this with a staging environment first and create back ups. Never run this directly in production unless you are 100% sure everything works:
- Get the latest ORY Hydra binary or docker image from the 1.0.0 branch.
- Run
$ export DATABASE_URL=<your-database-url>
. - If you want to keep using Access Control Policies and the Warden API, you must install ORY Keto using the binaries or the docker image:
$ keto migrate hydra $DATABASE_URL
.$ keto migrate sql $DATABASE_URL
.- Read how to update the JWK storage: AES-GCM nonce storage. If you only use auto-generated keys and have never used POST or PUT on the
/keys
API, you can probably just execute aDELETE FROM hydra_jwk
to just remove all the auto-generated keys. When starting the ORY Hydra 1.0.0 CLI the required keys will be re-generated automatically. $ hydra migrate $DATABASE_URL
.
- If you don't use Access Control Policies nor the Warden API, you can skip ORY Keto:
- Read how to update the JWK storage: AES-GCM nonce storage and read point 3.3 of this list.
$ hydra migrate $DATABASE_URL
.
$ export SCOPE_STRATEGY=DEPRECATED_HIERARCHICAL_SCOPE_STRATEGY
- this will set the scope strategy to the old scope strategy used in version 0.9.x. If you set this, you don't need to update the scopes your OAuth 2.0 Clients are allowed to request.$ hydra help serve
.$ hydra serve --your-flags
.
It's still a good idea to read through the changes in 0.10.0, for example: Response payload changes to /warden/token/allowed
. You can, however, skip the New consent flow subsection in the 0.10.0 section. All required changes are explained in detail in this release's consent flow description.
ORY Hydra is now OpenID Connect Certified! Certification spans the OAuth 2.0 Authorize Code Flow, Implicit Flow, and Hybrid Flow as well as dynamic discovery.
The certification is one reason for the breaking changes in the consent app.
One change has been made to the introspection API which is that key aud
is no longer a string, but an array of strings.
As this claim has not been supported actively up until now, this will most likely not affect you at all.
Previously, we disabled the introspection of refresh tokens. This has now changed to comply with the OAuth 2.0 specification.
To distinguish tokens, use the token_type
in the introspection response. It can either be access_token
or refresh_token
.
Internal access control, access control policies, and the Warden API have moved to a separate project called ORY Keto. You will be able to run a combination of ORY Hydra, ORY Oathkeeper, and ORY Keto which will be backwards compatible with ORY Hydra before the 1.0.0 release. This section explains how to upgrade and links to an example explaining the set up of the three services.
This means that ORY Hydra has no longer any type of internal access control. Endpoints such as POST /clients
no longer
require access tokens to be accessed. You must secure these endpoints yourself. For more information, click here.
ORY Keto handles access control using access control policies. The project currently supports the Warden API, Access Control Policy management, and Roles (previously known as Warden Groups). ORY Keto is independent from ORY Hydra as it does not rely on any proprietary APIs but instead uses open standards such as OAuth 2.0 Token Introspection and the OAuth 2.0 Client Credentials Grant to authenticate credentials. ORY Keto can be used as a standalone project, and might even be used with other OAuth 2.0 providers, opening up tons of possible use cases and scenarios. To learn more about the project, head over to github.com/ory/keto.
Assuming that you have the 1.0.0 release binary of ORY Hydra and ORY Keto locally installed, you can migrate the existing policies and Warden Groups using the migrate commands. Please back up your database before doing this:
$ export DATABASE_URL=<your-database-url>
# Migrate the policies and warden groups to keto
$ keto migrate hydra $DATABASE_URL
# Create other Keto database schemas
$ keto migrate sql $DATABASE_URL
# Run Hydra migrations
$ hydra migrate sql $DATABASE_URL
Now you can run keto serve
and endpoints /policies
as well as /warden
will be available at ORY Keto's URL.
We have set up a docker-compose example of a set up that resembles ORY Hydra prior to this release. You can find the source and documentation at github.com/ory/examples.
If you find it difficult to run this set up but would like to use the old access control mechanisms, feel free to reach out to us at mailto:[email protected].
The Warden endpoints have moved to a new project. Thus, obviously, the URL changes too. The Warden API paths have changed as well:
/warden/allowed
is now/warden/subjects/authorize
/warden/token/allowed
is now/warden/oauth2/access-tokens/authorize
/warden/oauth2/clients/authorize
is a new endpoint that lets you authorize OAuth 2.0 Clients using their ID and secret.
The backwards compatible set up properly forwards the old paths. If you use that image and you have been using
http://my-hydra/warden/token/allowed
previously, you can still use that URL to access that functionality if the
backwards-compatible image is hosted at that location. This image does, however, currently not rewrite the request
and response payloads. If you think that's a good idea, let us know.
The request payload of these endpoints has changed:
/warden/token/allowed
- only keyscopes
was renamed toscope
in order to have a coherent API with any OAuth 2.0 endpoints which use thescope
for singular and plural:- Key
scopes
is nowscope
- a response body is{ "token": "...", "action": "...", "resource": "...", "scope": ["scope-a", "scope-b"] }
instead of (previously){ "token": "...", "action": "...", "resource": "...", "scopes": ["scope-a", "scope-b"] }
.
- Key
All other endpoints have not experienced any request payload changes.
The response payload of these endpoints has changed:
/warden/token/allowed
- keys have been changed to conform to the OAuth 2.0 Introspection response payload and offer a coherent API.- Key
grantedScopes
is nowscope
and is no longer an array string but rather a space-delimited string ("scope-a scope-b"). - Key
clientId
is nowclient_id
. - Key
issuedAt
is nowiat
. - Key
expires_at
is nowexp
. - Key
subject
is nowsub
. - Key
accessTokenExtra
is nowsession
and might be omitted if the OAuth 2.0 Introspection Endpoint does not provide session data. - Key
aud
("audience") has been added as a string array. - Key
iss
("issuer") has been added. - Key
nbf
("not before") has been added.
- Key
We are aware that these changes are rather serious, especially if you rely on the Warden API in each of your endpoints. If you have ideas on how to improve upgrading or offer a backwards compatible API, please open an issue and let us know.
All other endpoints have not experienced any response payload changes.
Warden Groups have been an experiment determined to simplify managing multiple subjects with the same access rights.
In ORY Keto, Warden Groups have been renamed to Roles and the endpoint has moved from /warden/groups
to /roles
.
No request or response payloads have changed, only the URL is a different one.
If you use the backwards-compatible image, you can access roles using the /warden/groups
path as you did before.
Previously, JSON Web Keys did not have to specify a unique id. JWKs
generated by ORY Hydra typically only used public
or private
as KeyID. This patch changes that and appends a unique id if no
KeyID was given. To be able to separate between public and private key
pairs in resource name, the public/private convention was kept.
This change targets specifically the OpenID Connect ID Token and HTTP TLS keys. The ID Token key was previously "hydra.openid.id-token:public" and "hydra.openid.id-token:private" which now changed to something like "hydra.openid.id-token:public:9a458aa3-65a0-4982-835f-343eec45183c" and "hydra.openid.id-token:private:fa353995-d77d-420a-b967-63bf0721271b" with the UUID part being random for every installation.
This change will help greatly with key rotation in the future.
If you rely on these keys in your applications and if they are hardcoded in some way, you may want to use the /.well-known/openid-configuration
or /.well-known/jwks.json
endpoints instead. Libraries, which handle these standards appropriately, exist for almost any
programming language.
These keys will be generated automatically if they do not exist yet in the database. No further steps for upgrading are required.
The consent flow has been refactored in order to implement session (login & consent) management in ORY Hydra and in order
to properly support OpenID Connect parameters such as prompt
, max_age
, and others.
First, the consent flow has been renamed to "User Login and Consent Flow". The consent app has been renamed to User Login Provider
and User Consent Provider
. If you implement both features (explained in the next sections) in one program, you can call
it the User Login and Consent Provider
.
A reference implementation of the new User Login and Consent Provider is available at github.com/ory/hydra-login-consent-node.
The major difference between the old and new flow is, that authentication (user login) and scope authorization (user consent) are now two separate endpoints.
The new User Login and Consent Flow is documented in the developer guide.
The CLI has changed in order to improve developer experience and adopt to the changes made with this release.
The command hydra host
has been renamed to hydra serve
as projects ORY Oathkeeper and ORY Keto use the serve
terminology
as well.
Because this patch removes the internal access control, no root client and root policy will be created upon start up. Thus,
environment variable FORCE_ROOT_CLIENT_CREDENTIALS
has been removed without replacement.
To better reflect what environment variables touch which system, ISSUER has been renamed to OAUTH2_ISSUER_URL
and
CONSENT_URL
has been renamed to OAUTH2_CONSENT_URL
.
Additionally, flag --dangerous-force-auto-logon
has been removed it has no effect any more.
The command hydra connect
has been removed as it no longer serves a purpose now that the internal access control
has been removed. Every command you call now needs the environment variable HYDRA_URL
(previously named CLUSTER_URL
)
which should point to ORY Hydra's URL. Removing this command has an additional benefit - privileged client IDs and secrets
will no longer be stored in a plaintext file on your system if you use this command.
As access control has been removed, most commands (except token user
, token client
, token revoke
, token introspect
)
work without supplying any credentials at all. The listed exceptions support setting an OAuth 2.0 Client ID and Client Secret
using flags --client-id
and --client-secret
or environment variables OAUTH2_CLIENT_ID
and OAUTH2_CLIENT_SECRET
.
All other commands, such as hydra clients create
, still support scenarios where you would need an OAuth2 Access Token.
In those cases, you can supply the access token using flag --access-token
or environment variable OAUTH2_ACCESS_TOKEN
.
Assuming that you would like to automate management in a protected scenario, you could do something like this:
$ token=$(hydra token client --client-id foo --client-secret bar --endpoint http://foobar)
$ hydra clients create --access-token $token ...
All commands now support the --endpoint
flag which sets the HYDRA_URL
in case you don't want to use environment variables.
Flags --id
and --secret
are now called --client-id
and --client-secret
.
Flags --client-id
and --client-secret
have been added.
Flag --scopes
has been renamed to --scope
.
This command has been renamed to hydra token introspect
to properly reflect that you are performing OAuth 2.0
Token Introspection.
Flags --client-id
and --client-secret
have been added.
Flag --scopes
has been renamed to --scope
.
As OAuth 2.0 specifies that terminology scope
does not have a plural scopes
, we updated the places where the
incorrect scopes
was used in order to provide a more consistent developer experience.
This command renamed flag --allowed-scopes
to --scope
.
This command is a relict of an old version of ORY Hydra which is, according to our metrics, not being used any more.
This command has moved to Keto. All commands work the same way, but you have to have Keto installed and replace hydra
with keto
. For example hydra policies create ...
is now keto policies create ...
This command has moved to Keto. All commands work the same way, but you have to have Keto installed and replace hydra groups
with keto roles
. For example hydra groups create ...
is now keto roles create ...
As the SDK is code-generated, and we are not specialists in every language, we have only documented changes to the Go API. Please help improving this section by adding upgrade guides for the SDK you upgraded.
The following methods have been moved.
- The Access Control Policy SDK has moved to ORY Keto:
CreatePolicy(body swagger.Policy) (*swagger.Policy, *swagger.APIResponse, error)
is now available viagithub.com/ory/keto/sdk/go/keto
. The method signature has not changed, apart from typesgithub.com/ory/hydra/sdk/go/hydra/swagger
now being included fromgithub.com/ory/keto/sdk/go/keto/swagger
.DeletePolicy(id string) (*swagger.APIResponse, error)
is now available viagithub.com/ory/keto/sdk/go/keto
. The method signature has not changed, apart from typesgithub.com/ory/hydra/sdk/go/hydra/swagger
now being included fromgithub.com/ory/keto/sdk/go/keto/swagger
.GetPolicy(id string) (*swagger.Policy, *swagger.APIResponse, error)
is now available viagithub.com/ory/keto/sdk/go/keto
. The method signature has not changed, apart from typesgithub.com/ory/hydra/sdk/go/hydra/swagger
now being included fromgithub.com/ory/keto/sdk/go/keto/swagger
.ListPolicies(offset int64, limit int64) ([]swagger.Policy, *swagger.APIResponse, error)
is now available viagithub.com/ory/keto/sdk/go/keto
. The method signature has not changed, apart from typesgithub.com/ory/hydra/sdk/go/hydra/swagger
now being included fromgithub.com/ory/keto/sdk/go/keto/swagger
.UpdatePolicy(id string, body swagger.Policy) (*swagger.Policy, *swagger.APIResponse, error)
is now available viagithub.com/ory/keto/sdk/go/keto
. The method signature has not changed, apart from typesgithub.com/ory/hydra/sdk/go/hydra/swagger
now being included fromgithub.com/ory/keto/sdk/go/keto/swagger
.
- The Warden Group SDK has moved to Keto:
AddMembersToGroup(id string, body swagger.GroupMembers) (*swagger.APIResponse, error)
is nowAddMembersToRole(id string, body swagger.RoleMembers) (*swagger.APIResponse, error)
and is now available viagithub.com/ory/keto/sdk/go/keto
.CreateGroup(body swagger.Group) (*swagger.Group, *swagger.APIResponse, error)
is nowCreateRole(body swagger.Role) (*swagger.Role, *swagger.APIResponse, error
and is now available viagithub.com/ory/keto/sdk/go/keto
.DeleteGroup(id string) (*swagger.APIResponse, error)
is nowDeleteRole(id string) (*swagger.APIResponse, error)
and is now available viagithub.com/ory/keto/sdk/go/keto
.ListGroups(member string, limit, offset int64) ([]swagger.Group, *swagger.APIResponse, error)
is nowListRoles(member string, limit int64, offset int64) ([]swagger.Role, *swagger.APIResponse, error)
and is now available viagithub.com/ory/keto/sdk/go/keto
.GetGroup(id string) (*swagger.Group, *swagger.APIResponse, error)
is nowGetRole(id string) (*swagger.Role, *swagger.APIResponse, error)
and is now available viagithub.com/ory/keto/sdk/go/keto
.RemoveMembersFromGroup(id string, body swagger.GroupMembers) (*swagger.APIResponse, error)
is nowRemoveMembersFromRole(id string, body swagger.RoleMembers) (*swagger.APIResponse, error)
and is now available viagithub.com/ory/keto/sdk/go/keto
.
- The Warden API SDK has moved to Keto:
DoesWardenAllowAccessRequest(body swagger.WardenAccessRequest) (*swagger.WardenAccessRequestResponse, *swagger.APIResponse, error)
is nowIsSubjectAuthorized(body swagger.WardenSubjectAuthorizationRequest) (*swagger.WardenSubjectAuthorizationResponse, *swagger.APIResponse, error)
. Please check out the changes to the request/response body as well.DoesWardenAllowTokenAccessRequest(body swagger.WardenTokenAccessRequest) (*swagger.WardenTokenAccessRequestResponse, *swagger.APIResponse, error)
is nowIsOAuth2AccessTokenAuthorized(body swagger.WardenOAuth2AccessTokenAuthorizationRequest) (*swagger.WardenOAuth2AccessTokenAuthorizationResponse, *swagger.APIResponse, error)
. Please check out the changes to the request/response body as well.
- The Consent API SDK has been deprecated:
AcceptOAuth2ConsentRequest(id string, body swagger.ConsentRequestAcceptance) (*swagger.APIResponse, error)
has been removed without replacement.GetOAuth2ConsentRequest(id string) (*swagger.OAuth2ConsentRequest, *swagger.APIResponse, error)
has been removed without replacement.RejectOAuth2ConsentRequest(id string, body swagger.ConsentRequestRejection) (*swagger.APIResponse, error)
has been removed without replacement.
- The Login & Consent API SDK has been added:
AcceptConsentRequest(challenge string, body swagger.AcceptConsentRequest) (*swagger.CompletedRequest, *swagger.APIResponse, error)
AcceptLoginRequest(challenge string, body swagger.AcceptLoginRequest) (*swagger.CompletedRequest, *swagger.APIResponse, error)
RejectConsentRequest(challenge string, body swagger.RejectRequest) (*swagger.CompletedRequest, *swagger.APIResponse, error)
RejectLoginRequest(challenge string, body swagger.RejectRequest) (*swagger.CompletedRequest, *swagger.APIResponse, error)
GetLoginRequest(challenge string) (*swagger.LoginRequest, *swagger.APIResponse, error)
GetConsentRequest(challenge string) (*swagger.ConsentRequest, *swagger.APIResponse, error)
Additionally, the following methods have been removed as they were of very little use and also mixed the Client Credentials
flow with the Authorize Code Flow which lead to weird usage. It's much easier to configure clientcredentials.Config
or
oauth2.Config
yourself.
GetOAuth2ClientConfig() (*clientcredentials.Config)
GetOAuth2Config() (*oauth2.Config)
The health check endpoint has moved from /health/status
to /health/alive
. We set up a 308 redirect from /health/status
to /health/alive
so this should not cause any issues.
The /health/alive
endpoint returns 200 OK
as soon as the HTTP server is responsive. Another endpoint /health/ready
was added which returns 200 OK
only if the database connection is working as well.
As part of this change, function getInstanceStatus
of the SDK is now isInstanceAlive
and isInstanceReady
.
Previously, if you had a typo in the JSON (e.g. client_nme
instead of client_name
), ORY Hydra simply ignored that key.
Now, an error is thrown if unknown JSON keys are included.
ORY Hydra now uses UTC everywhere, reducing the possibility of errors stemming from different timezones.
Each endpoint that returns a list of items now supports pagination using limit
and offset
query parameters.
An endpoint (/oauth2/flush
) has been added that allows you to flush old access tokens.
An endpoint /health/prometheus
for providing data to Prometheus has been added.
This release resolves a security issue (reported by platform.sh) related to the fosite storage implementation in this project. Fosite used to pass all of the request body from both authorize and token endpoints to the storage adapters. As some of these values are needed in consecutive requests, the storage adapter of this project chose to drop all of the key/value pairs to the database in plaintext.
This implied that confidential parameters, such as the client_secret
which can be passed in the request body since
fosite version 0.15.0, were stored as key/value pairs in plaintext in the database. While most client secrets are generated
programmatically (as opposed to set by the user) and most popular OAuth2 providers choose to store the secret in plaintext
for later retrieval, we see it as a considerable security issue nonetheless.
The issue has been resolved by sanitizing the request body and only including those values truly required by their
respective handlers. This also implies that typos (eg client_secet
) won't "leak" to the database.
There are no special upgrade paths required for this version.
This issue does not apply to you if you do not use an SQL backend. If you do upgrade to this version, you need to run
hydra migrate sql path://to.your/database
.
If your users use POST body client authentication, it might be a good move to remove old data. There are multiple ways of doing that. Back up your data before you do this:
- Radical solution: Drop all rows from tables
hydra_oauth2_refresh
,hydra_oauth2_access
,hydra_oauth2_oidc
,hydra_oauth2_code
. This implies that all your users have to re-authorize. - Sensitive solution: Replace all values in column
form_data
in tableshydra_oauth2_refresh
,hydra_oauth2_access
with an empty string. This will keep all authorization sessions alive. Tableshydra_oauth2_oidc
andhydra_oauth2_code
do not contain sensitive information, unless your users accidentally sent the client_secret to the/oauth2/auth
endpoint.
We would like to thank platform.sh for sponsoring the development of a patch that resolves this issue.
The experimental endpoint /health/metrics
has been removed as it caused various issues such as increased memory usage,
and it was apparently not used at all.
This release has a minor breaking change in the experimental Warden Group SDK:
FindGroupsByMember(member string) ([]swagger.Group, *swagger.APIResponse, error)
is now
ListGroups(member string, limit, offset int64) ([]swagger.Group, *swagger.APIResponse, error)
.
The change has to be applied in a similar fashion to other SDKs generated using swagger.
Leave the member
parameter empty to list all groups, and add it to filter groups by member id.
This release has several major improvements, and some breaking changes. It focuses on cryptographic security by leveraging best practices that emerged within the last one and a half years. Before upgrading to this version, make a back up of the JWK table in your SQL database.
This release requires running hydra migrate sql
before hydra host
.
The most important breaking changes are the SDK libraries, the new consent flow, the AES-GCM improvement, and the response payload changes to the warden.
We know that these are a lot of changes, but we highly recommend upgrading to this version. It will be the last before releasing 1.0.0.
The introspection endpoint was previously accessible to anyone with valid client credentials or a valid access token. According to spec, the introspection endpoint should be protected by additional access control mechanisms. This version introduces new access control requirements for this endpoint.
The client id of the basic authorization / subject of the bearer token must be allowed action introspect
on resource rn:hydra:oauth2:tokens
. If an access token is used for authorization, it needs to be granted the
hydra.introspect
scope.
Previously, the consent flow looked roughly like this:
- App asks user for Authorization by generating the authorization URL (http://hydra.mydomain.com/oauth2/auth?client_id=...).
- Hydra asks browser of user for authentication by redirecting to the Consent App with a consent challenge (http://login.mydomain.com/login?challenge=xYt...).
- Retrieves a RSA 256 public key from Hydra.
- Uses said public key to verify the consent challenge.
- User logs in and authorizes the requested scopes
- Consent app generates the consent response
- Retrieves a private key from Hydra which is used to sign the consent response.
- Creates a response message and sign with said private key.
- Redirects the browser back to Hydra, appending the consent response (http://hydra.mydomain.com/oauth2/auth?client_id=...&consent=zxI...).
- Hydra validates consent response and generates access tokens, authorize codes, refresh tokens, and id tokens.
This approach had several disadvantages:
- Validating and generating the JSON Web Tokens (JWTs) requires libraries for each language
- Because libraries are required, auto generating SDKs from the swagger spec is impossible. Thus, every language requires a maintained SDK which significantly increases our workload.
- There have been at least two major bugs affecting almost all JWT libraries for any language. The spec has been criticised for it's mushy language.
- The private key used by the consent app for signing consent responses was originally thought to be stored at the consent app, not in Hydra. However, since Hydra offers JWK storage, it was decided to use the Hydra JWK store per default for retrieval of the private key to improve developer experience. However, to make really sense, the private key should have been stored at the consent app, not in Hydra.
- Private/Public keypairs need to be fetched on every request or cached in a way that allows for key rotation, complicating the consent app.
- There is currently no good mechanism for rotating JWKs in Hydra's storage.
- The consent challenge / response has a limited length as it's transmitted via the URL query. The length of a URL is limited.
Due to these reasons we decided to refactor the consent flow. Instead of relying on JWTs using RSA256, a simple HTTP call is now enough to confirm a consent request:
- App asks user for Authorization by generating the authorization URL (http://hydra.mydomain.com/oauth2/auth?client_id=...).
- Hydra asks browser of user for authentication by redirecting to the Consent App with a unique consent request id (http://login.mydomain.com/login?consent=fjad2312).
- Consent app makes a HTTP REST request to
http://hydra.mydomain.com/oauth2/consent/requests/fjad2312
and retrieves information on the authorization request. - User logs in and authorizes the requested scopes
- Consent app accepts or denies the consent request by making a HTTP REST request to
http://hydra.mydomain.com/oauth2/consent/requests/fjad2312/accept
orhttp://hydra.mydomain.com/oauth2/consent/requests/fjad2312/reject
. - Redirects the browser back to Hydra.
- Hydra validates consent request by checking if it was accepted and generates access tokens, authorize codes, refresh tokens, and id tokens.
Learn more on how the new consent flow works in the guide: https://ory.gitbooks.io/hydra/content/oauth2.html#consent-flow
Previously, the audience terminology was used as a synonym for OAuth2 client IDs. This is no longer the case. The audience
is typically a URL identifying the endpoint(s) the token is intended for. For example, if a client requires access to
endpoint http://mydomain.com/users
, then the audience would be http://mydomain.com/users
.
This changes the payload of /warden/token/allowed
and is incorporated in the new consent flow as well. Please note
that it is currently not possible to set the audience of a token. This feature is tracked with here.
IMPORTANT NOTE: In OpenID Connect ID Tokens, the token is issued for that client. Thus, the aud
claim must equal
to the client_id
that initiated the request.
Previously, the response of the warden endpoint contained shorthands like aud
, iss
, and so on. Those have now been changed
to their full names:
sub
is now namedsubject
.scopes
is now namedgrantedScopes
.iss
is now namedissuer
.aud
is now namedclientId
.iat
is now namedissuedAt
.exp
is now namedexpiresAt
.ext
is now namedaccessTokenExtra
.
The Go SDK was completely replaced in favor of a SDK based on swagger-codegen
. Unfortunately this means that
any code relying on the old SDK has to be replaced. On the bright side the dependency tree is much smaller as
no direct dependencies to ORY Hydra's code base exist any more.
Read more on it here: https://ory.gitbooks.io/hydra/content/sdk/go.html
GET /health
is nowGET /health/status
GET /health/stats
is nowGET /health/metrics
GET /warden/groups
now returns a list of groups, not just a list of strings (group ids).
The previous scope matching strategy has been replaced in favor of a wildcard-based matching strategy. Previously,
foo
matched foo
and foo.bar
and foo.baz
. This is no longer the case. So foo
matches only foo
. Matching
subsets is possible using wildcards. foo.*
matches foo.bar
and foo.baz
.
This change makes setting scopes more explicit and is more secure, as it is less likely to make mistakes.
Read more on this strategy here.
To fall back to hierarchical scope matching, set the environment variable SCOPE_STRATEGY=DEPRECATED_HIERARCHICAL_SCOPE_STRATEGY
.
This feature might be fully removed in a later version.
Our use of crypto/aes
's AES-GCM was replaced in favor of cryptopasta/encrypt
.
As this includes a change of how nonces are appended to the ciphertext, ORY Hydra will be unable to decipher existing
databases.
There are two paths to migrate this change:
- If you have not added any keys to the JWK store:
- Stop all Hydra instances.
- Drop all rows from the
hydra_jwk
table. - Start one Hydra instance and wait for it to boot.
- Restart all remaining Hydra instances.
- If you added keys to the JWK store:
- If you can afford to re-generate those keys:
- Write down all key ids you generated.
- Stop all Hydra instances.
- Drop all rows from the
hydra_jwk
table. - Start one Hydra instance and wait for it to boot.
- Restart all remaining Hydra instances.
- Regenerate the keys and use the key ids you wrote down.
- If you can not afford to re-generate the keys:
- Export said keys using the REST API.
- Stop all Hydra instances.
- Drop all rows from the
hydra_jwk
table. - Start one Hydra instance and wait for it to boot.
- Restart all remaining Hydra instances.
- Import said keys using the REST API.
- If you can afford to re-generate those keys:
The signature algorithm used to generate authorize codes, access tokens, and refresh tokens has been upgraded from HMAC-SHA256 to HMAC-SHA512. With upgrading to alpha.9, all previously issued authorize codes, access tokens, and refresh will thus be rendered invalid. Apart from some re-authorization procedures, which are usually automated, this should not have any significant impact on your installation.
The HS256 (symmetric/shared keys) JWK Generator now uses the full 256 bit range to generate secrets instead of a predefined rune sequence. This change only affects keys generated in the future.
The JWK algorithm ES521
was renamed to ES512
. If you want to generate a key using this algorithm, you have to use
the update name in the future.
This release removes build tags -http
, -automigrate
, -without-telemetry
from the docker hub repository and replaces
it with a new and tiny (~6MB) docker image containing the binary only. Please note that this docker image does not have
a shell, which makes it harder to penetrate.
Instead of relying on tags to pass arguments, it is now possible to pass command arguments such as docker run oryd/hydra:v0.10.0 host --dangerous-force-http
directly.
Version 0.10.8 reintroduces an image with a shell, appended with tag -alpine
.
It is now possible to alter resource name prefixes (rn:hydra
) using the RESOURCE_NAME_PREFIX
environment variable.
- It is now possible to refresh openid connect tokens using the refresh_token grant. An ID Token is issued if the scope
openid
was requested, and the client is allowed to receive an ID Token.
To improve ORY Hydra and understand how the software is used, optional, anonymized telemetry data is shared with ORY. A change was made to help us understand which telemetry sources belong to the same installation by hashing (SHA256) two environment variables which make up a unique identifier. Click here to read more about how we collect telemetry data, why we do it, and how to enable or disable it.
This release adds the possibility to specify special characters in the FORCE_ROOT_CLIENT_CREDENTIALS
by www-url-decoding
the values. If you have characters that are not url safe in your root client credentials, please use the following
form to specify them: "FORCE_ROOT_CLIENT_CREDENTIALS=urlencode(id):urlencode(secret)"
.
This version adds performance metrics to /health
and sends anonymous usage statistics to our servers, click here for more
details on this feature and how to disable it.
This PR improves some performance bottlenecks, offers more control over Hydra, moves to Go 1.8, and moves the REST documentation to swagger.
Before applying this update, please make a back up of your database. Do not upgrade directly from versions below 0.7.0.
To upgrade the database schemas, please run the following commands in exactly this order
$ hydra help migrate sql
$ hydra help migrate ladon
$ hydra migrate sql mysql://...
$ hydra migrate ladon 0.6.0 mysql://...
Ladon was greatly improved with version 0.6.0, resolving various performance bottlenecks. Please read more on this release here.
Redis and RethinkDB are removed from the repository now and no longer supported, see this issue.
To reflect the GitHub organization rename, Hydra was moved from https://github.com/ory-am/hydra
to
https://github.com/ory/hydra
.
The method FindPoliciesForSubject
of the policy SDK was removed. Instead, List
was added. The HTTP endpoint GET /policies
no longer allows to query by subject.
To generate JWKs previously the payload at POST /keys
was { "alg": "...", "id": "some-id" }
. id
was changed to
kid
so this is now { "alg": "...", "kid": "some-id" }
.
SQL Migrations are no longer automatically applied. Instead you need to run hydra migrate sql
after upgrading
to a Hydra version that includes a breaking schema change.
Set the log format to json using export LOG_FORMAT=json
You can configure SQL connection limits by appending parameters max_conns
, max_idle_conns
, or max_conn_lifetime
to the DSN: postgres://foo:bar@host:port/database?max_conns=12
.
... and are swagger 2.0 spec.
Documentation on scopes (e.g. offline) was added.
Hydra now uses github.com/ory/herodot
for writing REST responses. This increases compatibility with other libraries
and resolves a few other issues.
Hydra is now capable of gracefully handling SIGINT.
Hydra now implements best practices for running HTTP servers that are exposed to the public internet.