Commit Graph

44 Commits

Author SHA1 Message Date
Björn Weinehall
6e6579ab59 Add ID token support 2021-12-17 16:25:02 +01:00
James Hinshelwood
be86791762 Add token deserialization workaround
This fixes token deserialization when the
serde_json/arbitrary_precision feature is enabled.

See https://github.com/serde-rs/json/issues/559 for details.

Co-authored-by: James Hinshelwood <james.hinshelwood@bigpayme.com>
2021-09-15 15:58:09 +01:00
Lewin Bormann
e63aa4b843 Merge pull request #146 from djrodgerspryor/custom_storage_options
Custom token storage
2021-04-01 22:53:36 +02:00
Daniel Rodgers-Pryor
fbf6c17916 Expose TokenInfo fields publically
For easier debugging, and for implementing custom storage solutions which might not use serde.
2021-03-25 21:11:26 +11:00
Lewin Bormann
68dba11408 Run rustfmt 2021-03-06 10:20:32 +01:00
Lewin Bormann
9a29525cd7 Move to literal string in panic! macro 2021-03-04 19:32:31 +01:00
Daniel Rodgers-Pryor
5ef498f801 Custom token storage
Allow users to build their own token storage system by implementing the `TokenStorage` trait. This allows use of more secure storage mechanisms like OS keychains, encrypted files, or secret-management tools.

Custom storage providers are Box-ed to avoid adding more generics to the API — the indirection cost will only apply if using a custom store.

I've added `anyhow` to allow easy handling of a wide range of errors from custom storage providers.
2021-02-06 22:59:00 +11:00
Lewin Bormann
d193431465 Make two more application secret types Debug 2020-10-27 11:10:30 +01:00
Glenn Griffin
36d186deb4 Authenticator now returns an AccessToken.
What was previously called Token is now TokenInfo and is merely an
internal implementation detail. The publicly visible type is now called
AccessToken and differs from TokenInfo by not including the refresh
token. This makes it a smaller type for users to pass around as well as
reducing the ways that a refresh token may be leaked. Since the
Authenticator is responsible for refreshing the tokens there isn't any
reason users should need to concern themselves with refresh tokens.
2019-12-18 09:07:45 -08:00
Glenn Griffin
635bd5e21a Fix a bug introduced in the storage layer.
When bloom filters were added the btreemap values changed to be a
vector of tokens to accomodate the possibility of bloom filter
collisions. The implementation naively just pushed new tokens onto the
vec even if they were replacing previous tokens meaning old tokens were
still kept around even after a refresh has replaced it. To fix this
efficiently the storage layer now tracks both a hash value and a bloom
filter along with each token. Their is a map keyed by hash for every
token that points to a reference counted version of the token, and each
token also exists in a separate vector. Updates to existing tokens
happens in place, when new entries are added they are added to both data
structures.
2019-12-18 09:07:45 -08:00
Glenn Griffin
0525926bb2 Improve Token
Remove expires_in in favor of only having an expires_at DateTime field.
Add a from_json method that deserializes from json data into the
appropriate Token (or Error) and use that consistently throughout the
codebase.
2019-12-18 09:07:45 -08:00
Glenn Griffin
ca453c056c Improve documentation 2019-12-18 08:59:43 -08:00
Glenn Griffin
e5aa32b3cf Tidy up some imports.
No more need to macro_use serde. Order the imports consistently (albeit
somewhat arbitrary), starting with items from this crate, followed by
std, followed by external crates.
2019-12-18 08:59:43 -08:00
Glenn Griffin
0fe66619dd Minimize the number of items on the rustdoc landing page.
Restructure the modules and imports to increase the signal to noise
ration on the cargo doc landing page. This includes exposing some
modules as public so that they can contain things that need to be public
but that users will rarely need to interact with. Most items from
types.rs were moved into an error.rs module that is now exposed
publicly.
2019-12-18 08:57:24 -08:00
Glenn Griffin
3aadc6b0ef Major refactor of the public API.
1) Remove the GetToken trait. The trait seemed to be organically
designed. It appeared to be mostly tailored for simplifying the
implementation since there was no way for users to provide their own
implementation to Authenticator. It sadly seemed to get in the way of
implementations more than it helped. An enum representing the known
implementations is a more straightforward way to accomplish the goal and
also has the benefit of not requiring Boxing when returning features
(which admittedly is a minor concern for this use case).

2) Reduce the number of type parameters by using trait object for
delegates. This simplifies the code considerably and the performance
impact of virtual dispatch for the delegate calls is a non-factor.

3) With the above two simplifications it became easier to unify the
public interface for building an authenticator. See the examples for how
InstalledFlow, DeviceFlow, and ServiceAccount authenticators are now created.
2019-12-18 08:57:24 -08:00
Glenn Griffin
8489f470a4 cargo clippy fixes 2019-12-18 08:53:22 -08:00
Glenn Griffin
4bd81c3263 cargo fmt 2019-12-18 08:53:22 -08:00
Glenn Griffin
2cf2e465d1 Add JsonErrorOr enum to make json error handling more concise/consistent.
JsonErrorOr is an untagged enum that is generic over arbitrary data.
This means that when deserializing JsonErrorOr<T> it will first check
the json field for an 'error' attribute. If one exists it will
deserialize into the JsonErrorOr::Err variant that contains a JsonError.
If the message doesn't contain an 'error' field it will attempt to
deserialize T into he JsonErrorOr::Data variant.
2019-12-18 08:53:22 -08:00
Glenn Griffin
9542e3a9f1 Remove instances of cloning ApplicationSecret
ApplicationSecret is not a small struct. This removes the instances
where it's cloned in favor of passing a shared reference.
2019-12-18 08:53:22 -08:00
Glenn Griffin
696577aa01 Accept scopes as a slice of anything that can produce a &str.
Along with the public facing change the implementation has been modified
to no longer clone the scopes instead using the pointer to the scopes
the user provided. This greatly reduces the number of allocations on
each token() call.

Note that this also changes the hashing method used for token storage in
an incompatible way with the previous implementation. The previous
implementation pre-sorted the vector and hashed the contents to make the
result independent of the ordering of the scopes. Instead we now combine
the hash values of each scope together with XOR, thus producing a hash
value that does not depend on order without needing to allocate another
vector and sort.
2019-12-18 08:53:22 -08:00
Glenn Griffin
0f29c258c6 FlowType isn't used for anything. Remove it. 2019-12-18 08:53:22 -08:00
Glenn Griffin
93cbd91341 Move to std::futures to support async/await. 2019-12-18 08:53:22 -08:00
Cameron Taggart
b7703d40b4 make refresh_token an option 2019-11-11 22:44:31 +00:00
Glenn Griffin
c33d0b8481 Make RequestError Sync
This requires enforcing that errors returned from TokenStorage
implementations are Send, which the ones in this crate are, but is a
breaking change because any external implementations may be returning
errors that are !Sync currently.

The motivation for this change is that Box<dyn Error + Send> is not as fully
supported within the rust stdlib as Box<dyn Error + Send + Sync>. In
particular there exists these two From impls:

impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a>
impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a>

but no corresponding impl for

impl<'a, E: Error + Send + 'a> From<E> for Box<dyn Error + Send + 'a>

This may just be an oversight in the rust stdlib that could be fixed,
but in practice it means that dealing with 'Error + Send' types is not
the most ergonomic because the '?' operator can't be used to convert
from a Box<dyn Error + Send> to a Box<dyn Error>.

Since the current implementations (not counting any external ones that
may exist) implement Sync this seems like a good tradeoff to make it a
little easier to use in an ergonomic way.
2019-08-30 11:53:45 -07:00
Glenn Griffin
2b18f3679e Modify GetToken::token.
Change it to accept an iterator of items that can be converted to
`String`s rather than an iterator of items that can be referenced as
`&str`s.

Primarily this allows it to be called with a larger variety of inputs.
For example ::std::env::args().skip(1) can now be passed directly to
token, where before it would first need to be collected into a vector.

Since all implementations unconditionally collected the iterator into a
vector this shouldn't have any negative impact on performance and should
actually reduce the number of allocations in some uses.

It simplifies the signature since the lifetime bounds are no longer
required.
2019-08-08 14:32:24 -07:00
Mark Catley
ff8b3ede30 Updates to allow retrieving a token using the device flow on Salesforce. 2019-06-28 09:49:52 +12:00
Lewin Bormann
602ea1565d refactor(errors): Move almost everything to RequestError.
This is nicer than stupid Box<dyn Error+Send> everywhere.
2019-06-22 21:53:55 +02:00
Lewin Bormann
9e4a7e6d49 refactor(StringError): Take more comfortable types in StringError::new 2019-06-14 10:44:44 +02:00
Lewin Bormann
f034b8bea4 imp(ServiceAccountAccess): Print exact error if server returns one.
Prevents #76.
2019-06-13 16:16:51 +02:00
Lewin Bormann
6b05056b05 imp(expiry): Treat tokens with < 1 minute life left as expired.
Fixes #78.
2019-06-13 16:08:23 +02:00
Lewin Bormann
a656df6b74 feat(GetToken): Add application_secret method to GetToken trait.
This makes decoupling Authenticator and individual flows easier while
allowing for refreshing tokens.
2019-06-13 15:29:18 +02:00
Lewin Bormann
58383f9a03 refactor(DeviceFlow): Make DeviceFlow work with Futures 2019-06-12 18:43:30 +02:00
Lewin Bormann
732e594962 refactor(InstalledFlow): Implement GetToken for InstalledFlow 2019-06-12 14:40:08 +02:00
Lewin Bormann
59b2b03b7d rewrite(serviceaccount): Rewrite ServiceAccountAccess to use futures.
Also add example/test to check if obtaining tokens using JWTs works.
2019-06-12 13:50:56 +02:00
Lewin Bormann
39fe5f1d25 chore(syntax): Use dyn everywhere and remove unused imports. 2019-06-12 00:05:32 +02:00
Lewin Bormann
c2fbee4dc8 rewrite(installed): Make the InstalledFlow asynchronous with futures. 2019-06-11 23:29:12 +02:00
Guy Taylor
9f7f3c3b95 Upgrade to Hyper v0.12
This upgrade Hyper to v0.12 and updats to code to work for it. It has
being done with the minimum code change and so the logic is still
aukward for the futures model. This should be addressed in later commits
but I did not want to compilcate an already large commit.
2019-05-26 11:08:32 +02:00
Guy Taylor
b96cfcd66a Format to fustfmt defaults and force lint check in Travis 2019-02-21 20:46:00 +00:00
Jamie Turner
ab4b2c2fd4 Rust 2018 edition modifications. 2019-01-04 12:43:19 -08:00
Igor Gnatenko
e634d3f139 deps: update chrono to 0.4
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
2018-07-25 22:47:52 +02:00
Lewin Bormann
a8479b8ddb feat(device): Make the Device flow independent of Google
This is a breaking change; it's supposed to fix #1. Also, it's a
proposal -- not sure if the benefits outweigh the cost of this.

The example/auth.rs binary is not broken by this, as it doesn't use the
API that changed. The tests have been updated accordingly.
2016-10-09 09:55:33 +02:00
Lewin Bormann
ed0a3c4990 fix(types::Token): Don't panic if refresh_token is empty
Service account tokens don't set the refresh_token. Checking the
access_token field should be sufficient.
2016-09-21 09:24:09 +02:00
Lewin Bormann
2bdb47375a feat(refactor): Move StringError from authenticator to types module 2016-09-20 20:18:45 +02:00
Lewin Bormann
85b12dd3e8 refactor(common): Rename common -> types 2016-08-31 20:01:24 +02:00