Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add functionality to exchange one token to another #150

Merged
merged 7 commits into from
Dec 21, 2016

Conversation

Hanspagh
Copy link
Contributor

Makes it possible to exchange a token with type 'refresh' to a token with type 'token', like we discussed in #111, it will play nicely with guardianDB once ueberauth/guardian_db#15

Exchange a token with type 'refresh' for a token with type 'token'
with the same claims but a shorter expiry time.

The token with typ 'refresh' will be revoked after the exhange
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the normal proceedure to revoke the refresh token? I thought these stayed valid and could be used multiple times.

@hassox
Copy link
Member

hassox commented May 17, 2016

This looks pretty good, just the q about revoking a refresh token. I could be wrong but my understanding is that they should stick around.

Also can you please add some words to the readme and changelog?

Thanks :D

@Hanspagh
Copy link
Contributor Author

I guess we could make it up to the user to revoke it, or create two different methods exchangeAndRevoke and exchange. What do you think?
I am updating the readme as we speak.

@Hanspagh
Copy link
Contributor Author

Hanspagh commented May 18, 2016

I just realized that you can use the refresh token as a normal token. Is this the case or did I miss something?
Edit
I guess it can be solved by setting the typ in EnsureAutenticated, but this should properly be mention in the Readme

|> Guardian.Claims.ttl
|> Map.delete("ttl")
defp set_ttl(claims, type) do
if type === "refresh" do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to support :refresh? We use atoms elsewhere.

Copy link
Contributor Author

@Hanspagh Hanspagh May 19, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, but this ensures that we can set a default living time for the refresh tokens
Edit:
I read your comment wrong, the reason I used "refresh" is because guardian currently use "token" as default

@hassox
Copy link
Member

hassox commented May 20, 2016

@Hanspagh correct you could use it. Once you start using different types of tokens EnsureAuthenticated should check the typ field. I use access tokens for normal calls and other types as appropriate.

@hassox
Copy link
Member

hassox commented May 20, 2016

As an example, here's my plug for one of my apps

  pipeline :api_auth do
    plug Guardian.Plug.VerifyHeader, realm: "bearer"
    plug Guardian.Plug.EnsureAuthenticated, typ: "access", handler: MyAwesomeApp.Api.V1.ApiAuthErrorHandler
    plug Guardian.Plug.LoadResource
  end

@Hanspagh
Copy link
Contributor Author

Makes sense, my only concern is that if someone isn't aware of this, you could authenticate your self with a refresh token, which defeats the whole purpose of this. So we might consider having EnsureAuthenticated check for the typ "token" per default. What do you think?

@hassox
Copy link
Member

hassox commented May 27, 2016

I'm not sure if that would be good or not. I'm thinking about pipelines and setting the token type there. It might be ok. Let me percolate on it a bit. Also I think we should change the default type to 'access' rather than 'token'. Token doesn't really mean anything.

@Hanspagh
Copy link
Contributor Author

Hanspagh commented Jun 1, 2016

I think you are right 'access' makes much more sense then token. If we don't make it a default in EnsureAuthenticated as well, I think we should at least inform the user about the implications.

@Hanspagh
Copy link
Contributor Author

Any progress on this?

@hassox
Copy link
Member

hassox commented Jun 13, 2016

Hey @Hanspagh thanks for pinging on this one. I think we definitely need an exchange function but I don't think we should limit it to only refresh tokens. You could exchange any kind. I do like the refresh TTL of the token too and would love to see it come in.

I think what would be great is:

  1. we add an exchange function that can handle whatever type of token and exchange it for another. This should take the existing token, the new type, the old type and any options to modify
  2. We should change the existing default from token to access.
  3. Update the README to define the implications of using different token types
  4. add a configuration entry for token_ttl where you can specify the defaults of each type of token.

Thoughts?

@Hanspagh
Copy link
Contributor Author

I think the overall idea sounds really solid.
This allows to define your own token type and still benefit from the exchange functionality. The only downside I see is that someone could potentially exchange a "access" token for a "refresh" token.
We could predefine these two types and enforce some behavior to prevent that. What do you think?

@hassox
Copy link
Member

hassox commented Jun 14, 2016

Hmm true facts. I guess there's a couple of ways I can think of that we could deal with that.

  1. Add a config option that provides a mapping from -> to
  2. Add into the exchange function signature the expected from -> to. If the from doesn't match it doesn't work

I think 2 seems more natural to me. That way the calling code would be responsible:

Guardian.exchange(jwt, "refresh", "access")

Or in the case where it's many:

Guardian.exchange(jwt, ["refresh", "rememberMe"], "access")

Thoughts?

@Hanspagh
Copy link
Contributor Author

Seems good, I will start working on it

@Hanspagh
Copy link
Contributor Author

Here is first shot at the proposed solutions. Still missing docs and being able to modify the token created
Some questions:

  • Should we keep the ttl config, so we wont break existing projects, and just use it as a fallback if the token_ttl does not exists.
  • We might consider lowering the fallback ttl from 1000.000.000s to something more sense able or throw and error if there is no config

defp do_exchange(from_typ, to_typ, claims) do
if correct_typ?(claims, from_typ) do
{:ok, resource} = Guardian.serializer.from_token(claims["sub"])
case encode_and_sign(resource, to_typ, %{}) do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to drop some of the claims here and use the remaining claims. If we just use an empty map we'll lose any custom claims that were embedded in the 'refresh' token.

@Hanspagh
Copy link
Contributor Author

I will have a look. I have a very busy work week coming up, but I will be back in action the 27.

@Hanspagh
Copy link
Contributor Author

I am sorry for the huge delay on this, but I have fixed the two issues you mentioned namely; to handle atom types and not drop all claims when doing the exchange

@doomspork
Copy link
Member

Thank you @Hanspagh! @hassox any additional feedback?

@Hanspagh
Copy link
Contributor Author

Hanspagh commented Sep 8, 2016

If you don't have anymore feedback, I will update the docs and we can finish this.

@Moussenger
Copy link

When this pull request will be merged?

@doomspork
Copy link
Member

@hassox any final feedback? @Hanspagh do you mind rebasing?

@Hanspagh
Copy link
Contributor Author

I will update the docs and rebase it this weekend

@doomspork
Copy link
Member

Thank you @Hanspagh

@Hanspagh Hanspagh force-pushed the master branch 2 times, most recently from 9af62c4 to 5fd4edf Compare October 24, 2016 12:07
@Hanspagh
Copy link
Contributor Author

Okay, I did the rebase, and added some docs.
One thing we didn't talk about is the ability to have more than one token defined the the the config file.
Where should document this?

@Hanspagh
Copy link
Contributor Author

Hanspagh commented Dec 1, 2016

I am sorry for reviving this again, but I am pretty sure that we could just merge this?

@doomspork
Copy link
Member

Sorry for the delays @Hanspagh, I've not been following this thread. Let me review the changes and see about merging.

@doomspork doomspork merged commit 33d5bb2 into ueberauth:master Dec 21, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants