Details breaking changes and migration possibilities. Report missing information with an issue. For guides on larger migrations you may also request more detailed information.
This migration notice denotes work-in-progress (WIP) or planned changes (NEXT) before major releases on git version and will be updated into a single log when a major release or breaking minor release (before 1.0) is made. Both are intended to provide advance notice of expected interface changes and may be shifted back in work log arbitrarily. In that case, they will be moved to the according migration note.
This document is independent of the release notes.
Action is only required if you've implemented the accesstoken::Request
trait.
The authorization method now uses a special enum instead of a complex Option
type. The previous semantics map to the variants None
and UsernamePassword
.
When consuming this non-exhaustive trait you should treat unknown authorization
methods as authentication failure.
The crate has been split into a core (oxide-auth
) and several sub-crates for
each frontend version. The corresponding modules and features no longer exist.
Instead, it is expected that You additionally depend on the crate that
implements the web server bindings of your need. This decouples implementations
of generic primitives from servers and reduces dependencies.
A new attribute for the token type of the access token has been added, its enum
type has a Default
implementation that generates the Bearer
corresponding
variant. (This is only for forward compatibility. Such a feature is not yet
planned, and if it gets introduced depends on the usefulness of other token
types in practice). Add TokenType::Bearer
to all instances for the previous
behaviour.
The redirect URL registered with clients have been split into two variants: A
semantic URL and an exact URL. Use the RegisteredUrl::Semantic
constructor
for the behaviour of previous releases. An exact URL is stored as a character
string instead of a parsed URL. It is then also compared character by
character.
As advised in deprecation warnings, the iterators for public and private
extension data of a grant are now constructed via the public
and private
method respectively and the older iter_public
and iter_private
method have
been removed. The is_private
method of PublicExtensions
is now obsolete and
has been removed since the return type of private
is now correct.
The wrongly spelled and deprecated ephermal
constructor of the Assertion
grant generator has removed. Use the recommended replacement ephemeral
.
The refresh token in IssuedToken
is now an Option
. An empty token is still
accepted but now has the semantics of an existing, actually empty token. You do
not want to use this as it offers no security..
The Issuer::refresh
method no longer has a default implementation. To
replicate the old behaviour, its body should simply consist of Err(())
.
An empty refresh
token in the IssuedToken
will no longer inidicate support
for refreshing to the client. Furthermore, refresh tokens need to be
explicitely enabled for TokenSigner
as there is no good way to revoke them
and are mostly intended for usage in custom signers.
The iron frontend has been reworked greatly. It no longer wraps endpoint
related types into custom structs. Users who previously used these features and
want to transition quickly may replace IronGranter
with the Generic
struct
and the its flow creation methods with methods of that struct of with functions
found in frontends::simple::endpoint::*
. A more complete transition for
larger code bases would be implementing endpoint::Endpoint
yourself.
Note that MethodAuthorizer
got replaced by frontends::simple::FnSolicitor
and the IronAuthorizer
has been fully removed. SimpleAuthorization
was
superseeded by endpoint::OwnerAuthorization
.
Support for a Bearer token authorizing Middleware implementation has not yet
been implemented. Also, see the notes on QueryParamter
and module reordering
below in the general migration notes for v0.4.0
.
Below is a reverse chronological list of recommended migration notes. These have been collected while improving incrementally in preview versions. Read this list either by searching for required functionality from the top or tracing the outdated types from the bottom.
Bearer authorization provided by code_grant::resource
and
endpoint::ResourceFlow
now returns the extracted Grant
associated with an
authorized request. Therefore, additional logic based is safely enabled in the
successful case.
code_grant::endpoint
has been moved to a top-level module endpoint
. This
should hint to the fact that the code grant authorization will maybe not be the
only supported method.
Extensions will be implemented in such a way as to be used standalone.
While the simple
frontend offers some trait based AddonList
to make use of
multiple independent extensions at the same time, this is no longer required
for other frontends. The data portion of a GrantExtension
has been renamed to
the more unique Value
, and the simple
extension module extends on this
trait to offer AccessTokenAddon
and AuthorizationAddon
, simple traits to
implement only a portion of a fullblown system of extension at a time.
Serde support for NormalizedParameter
so that there is less confusion about
how to construct them and the potential pitfalls of dropping duplicate
keys-value pairs. Strongly assert their non-existence with the respective,
dedicated error code. The frontends duly use this to make good examples.
The code_grant::endpoint::ResponseKind
enum has been encapsulated in a
private struct (code_grant::endpoint::Template
) with dedicated methods to
retrieve status code and optional modification objects. With this change,
additional information and customization can be added to the response kind
without breaking the interface.
Primitives have been renamed:
authorizer::Storage
toauthorizer::AuthMap
. This is more in line with other primitives backed by an in-memory (hash-)map.generator::TokenGenerator
togenerator::TagGrant
. Additional emphasis on the fact that the generated tokens should be collision resistant for different grants but need not be deterministic (acts similar to a non-verifiable signature scheme). Also has better interop withgenerator::Assertion
by providing a variant ofTaggedAssertion
that hasSend + Sync + 'static
and provides an impl ofTagGrant
.
Generally rebuilt generator::TagGrant
–previously generator::TokenGenerator
:
fn generate(&self, ..)
tofn generate(&mut self, u64, &Grant)
. But for the standard implementations–which do not have any internal mutable state–the impl is also provided for&_
,Rc<_>
andArc<_>
.- The generics on
AuthMap
andTokenMap
now default to `Box<TagGrant + Send- Sync + 'static>
. This is sufficient for all
TagGrant` implementations provided here.
- Sync + 'static>
TaggedAssertion
now implements this trait differently. Since the signature was deterministic, this has silently broken the security ofTokenMap
by issuing the same access and refresh tokens. Since refresh was not provided, that did not matter :) The newcounter
that has to be kept by such authorizers/issuers makes this interaction secure even for repeating grants.
v0.4.0-preview.1
A HUGE refactor of the backend part of the library. For the actix
part, see the
relevant section.
Currently trying to streamline traits and method by making them less specialized and reusable or hiding complexity behind a more succinct interface. Part of this is cleaning up interfaces that were misguided by envisioning them with a too heavy focus on optimization but sacrificing usability in the process. And as it later turned out, this choice also introduced complicated inter-module dependencies that reduced the overall available design space. Sacrificing functionality for a small performance boost is not an acceptable tradeoff.
Documentation changes all around with an improved structure:
code_grant
contains core algorithms.code_grant::endpoint
contains the genericEndpoint
,WebRequest
,WebResponse
andxFlow
traits and structs to generalize frontend implementations. Also note the wording now refers to these features as 'Endpoint' related while 'frontend' is used for http-library specific components. When other OAuth methods are supported, this may instead move to its own top-level module.frontends::simple
contains reusable abstractions for endpoints. That is, an an owning request and response struct. Similar abstractions previously existed for test purposes only.
The following names have changed for consistency:
- Types of request-response mechanisms are now prefixed with the resource that the requesting party (i.e. the client) tries to access. In particular:
CodeRequest
,CodeFlow
, … toAuthorizationRequest
,AuthorizationFlow
GuardFlow
, … toResourceFlow
- The
OwnerAuthorizer
has been named toOwnerSolicitor
to emphasize its role in conjunction with the resource owner and avoid confusing with directly 'authorization' related types.
The standardization of a simple, reusable Endpoint
offers exiting new
possibilites. Foremost, a simple newtype wrapper around this and other
primitives imbues them with Actor
powers and messaging. Requests and
responses are now more composable so the former now has a simpler
representation and the necessity of tacking on owner owner consent information
has been moved to messages entirely. Messages for other primitive types have
been added, so that even a Registrar
or an Issuer
can be run as their own
actors. That might be very useful to attach them to a database backend.
The initial construction of a OAuthRequest
is now the result of an
OAuthFuture
that consumes the http request. This has simply been shifted from
the actix message constructors. Since OAuthRequest
now also implements
WebRequest
in a simple manner, many implementors will likely want to use a
newtype style to further customize error types and response representations.
Keep in mind that for a request to be useable as a message to an endpoint
actor, the error types of the two have to agree. This restriction may be lifted
in later versions.
Basic asynchronous handling of requests is provided with three top-level methods that return a boxed future of appropriate type. This leaves the internal representation open to future changes. The interface is currently more restrictive than necessary to keep the interface more stable. This special implementation buffers partial results from primitives to retry a flow when polling from one of its futures fails.
Registrar
now requires the result of bound_redirect
to have a lifetime
independent of self
. Instead of requiring a long-living reference to an
internal EncodedClient
, scope resolution has been moved to a separate method.
Rationale: This method required taking a borrow on whatever provided the registrar due to its entangled lifetimes. Since the return value was needed later in the authorization process the non-local borrow hindered simultaneous usage of other mutable members, even if those were local.
At the same time, this change implies that the underlying storage of a
Registrar
is no longer restricted to EncodedClient
and can use arbitrary
data structures.
Registrar
also no longer requires returning a RegisteredClient
in its
interface. The client
method has been replaced with
fn check(&self, client_id: &str, passphrase: Option<&[u8]>
which should perform the equivalent of
self.client(client_id).ok_or(Unspecified)?.check_authentication(passphrase)
while leaving the internal representation undetermined.
Rationale: Tries to avoid having any references into the inner representation
that do not refer to types which can be cloned into an owned representation.
Such types make it harder than necessary to create an interface with
messages/actors/async. Since the client
method had no other purpose than the
equivalent usage shown above, this choice should be fairly uncontroversial.
Authorizer
and Issuer
have gained a way to signal internal consistency
failure in their token lookup methods. The return type changed from
Option<Grant>
to Result<Option<Grant>, ()>
. If a custom implementation
previously did not rely on returning an error response, just wrap it in an
Ok
.
Construction of WebResponse
instances (e.g. by redirect_error
) has been
removed from WebResponse
. Instead, a new method response
has been added to
Endpoint
that may inspect the request and kind of response required. All
modifier functions such as client_error
, json
, etc. have also been reworked
to instead work on mutable references to the WebResponse
.
Rationale: It is the endpoint that contains the implementation specific logic.
Since the error can only be enriched with additional information or references
to other pages before it is converted to a WebResponse
, this logic is not
universal for implementations for WebResponse
but rather needs customization
from the endpoint.
Endpoints and responses can also rely on call restrictions to these new
methods. For example, all flows will at most call one body_
variants of
WebResponse
and Endpoint::response
will be called at most once per flow
execution. This could prove useful to high-performance implementations that
want to recycle response instances and avoiding allocation. It should be
possible to use a &mut _
as a WebResponse
in an endpoint implementation.
The previous OwnerAuthorizer
and OwnerAuthorization
have been renamed to
OwnerSolicitor
and OwnerConsent
to avoid confusion arising from the use of
'authorization'. Additionally, it has been integrated in the endpoint next to
other primitives, no frontend actually supported very different usage anyways.
The code_grant::frontend
flow design has been revamped into a unified trait.
This replaces the explicit …Flow
constructors while allowing greater
customization of errors, especially allowing the frontend to react in a custom
manner to primitive
errors or augment errors of its own type. This should
open the path to more flexible future
based implementations.
QueryParamter is now a private struct with several impl From<_>
as substitutes
for the previous enum variants. This should make frontend implementation more
straightforward by simply invoking .into()
while allowing introduction of
additional representations in a non-breaking change (variants of public enums
are strictly speaking breaking changes while new impls of crate types are not).
As an added bonus, this change enabled many more zero-copy representations for
query parameters.
Rationale: The previous version was not ergonomic to use while tempting users into relying on underlying libraries to correct not deduplicate key-value pairs. Note that for example the following is incorrect:
//! serde_urlencoded::from_str::<HashMap<String, String>>(query)?.normalize();
Instead, deserialize to NormalizedParameter
serde_urlencoded::from_str::<Vec<(String, String)>>(query)?.into_iter().collect();
The possibility to create a TokenSigner
instance based on a password has been
removed. The use of this was discouraged all along but this removes another
possible security pit fall. Note that you may want to migrate to a self-created
ring::hmac::SigningKey
instance, using a randomly generated salt and a
self-chosen, secure password based key derivation function to derive the key
bytes. Alternatively, you can now create a TokenSigner
that uses an ephemeral
key, i.e. the key will change for each program invocation, invalidating all
issued tokens of other program runs.
Rationale: Password based, low-entropy keys do not provide adequate security.
While the interface offered the ability to provide a high-entropy salt to
create a secure signing key, it was easy not to do so (and done in the examples
against the recommendation of the documentation). The scenario for the
examples, and by extension maybe the scenario of users, did not rely on
persistent keys. The new interface should offer high security both for a
configuration-free setup and a production environment. Relying on the standard
constructors for SigningKey
is intended to urge users to correctly use
high-entropy inputs such as the default rng of standard password hashing
algorithms.
A new simple frontend (frontends::simple
) has been introduced to serve as a
common denominator for other implementations. Its data types are built for
simplicity and used in tests, replacing the previous private test module
implementations.
Endpoint::Error
no longer requires traits bounds of From<OAuthError>
and
From<Request::Error>
. Instead, a dedicated callback method taking &mut self
of the endpoint does that conversion.
Rationale: The trait bounds puts some restrictions on implementing endpoints
with error types that are not defined in the current trait. Additionally, it
made it impossible to generalize over the underlying request type, as there is
no way to implemention impl<T> From<T> for ErrorType
, of course.
Extension have been redesigned. Instead of the backend iterating over a set of
extensions provided by the endpoint, the endpoint implementation now has full
control over the input and output extension data in a single function call. The
traits AuthorizationExtension
etc. have been moved to the new
frontends::simple
. They can NOT be used in the async portions of the actix
frontend.
Rationale: This is to allow groups of extensions working closely together, such as possibly for OpenID in the future. It also solves a few efficieny and design issues by leaving the representation more open to library users/frontends. Since extension do not provide guarantees on idempotency, they can not be simply retried. Therefore, the asynchronous interface of actix can not currently make use of them. Sorry.
Error variant namings and usages have been clarified. Specifically, such names should now correspond more closely to HTTP status codes where applicable.
** v0.4.0-preview0 **
Actix is the only fully supported framework for the moment as development begins
on trying to support async
based frameworks. This release is highly
experimental and some breaking changes may go unnoticed due to fully switching
the set of frontends. Please understand and open a bug report if you have any
migration issues.