Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OWIN external login refresh token

Tags:

c#

asp.net

owin

I'm using owin for my app, Web Api2 for working with data and MVC5 for view.

     static Startup()
    {
        PublicClientId = "self";

        UserManagerFactory = () => new UserManager<User, int>(new UserRepository());
        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/Account/Token"),
            AuthorizeEndpointPath = new PathString("/Account/ExternalLogin"),
            Provider = new ApplicationOAuthProvider(PublicClientId, UserManagerFactory),
            RefreshTokenProvider = new SimpleRefreshTokenProvider(),
            AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(59),
            AllowInsecureHttp = true,
        };

    }

When user is logged in through /Token?username=x&password=x&grant_type=password, it generates bearer token with refresh GUID for future refresh token /Token?grant_type=refresh_token, all is working okey.

My app can login through Facebook, etc, it's getting data I need from Facebook (email, etc) then I want to generate token with refresh GUID, problem is that for refreshing I need to pass data through /Token?username&password but my user doesn't have password, I tough to send additional parameter Scope and show what provider and provider key its using and to search in DB this user is registered and give him permission to generate token.

Is this good idea?

enter image description here

like image 324
Andrian Durlestean Avatar asked Oct 21 '22 05:10

Andrian Durlestean


2 Answers

I found solution, without using garnt_type=password:

This is my refresh token class that AuthroizationServer is using

     public class SimpleRefreshTokenProvider : IAuthenticationTokenProvider
    {
        private static ConcurrentDictionary<string, AuthenticationTicket> _refreshTokens =
            new ConcurrentDictionary<string, AuthenticationTicket>();

        public async Task CreateAsync(AuthenticationTokenCreateContext context)
        {.......}
        public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
        {.......}
    }

My AccountController is initialized like this:

    public AccountController()
        : this(Startup.UserManagerFactory(), Startup.OAuthOptions.AccessTokenFormat)
    {
    }

    public AccountController(UserManager<User, int> userManager, ISecureDataFormat<AuthenticationTicket> accessTokenFormat)
    {
        UserManager = userManager;
        AccessTokenFormat = accessTokenFormat;
        UserManager.UserValidator = new CustomUserValidator<User>(UserManager);
    }

Now I need to create AuthenticationTokenCreateContext and send it to my RefreshTokenProvider so it will add Refresh Guid in _refreshTokens, so when I will send my refreshGuid it will be valid. Where I'm creating Identity for ExternalUser

        ClaimsIdentity oAuthIdentity = await UserManager.CreateIdentityAsync(user,
        OAuthDefaults.AuthenticationType);
        AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.Id.ToString());
        oAuthIdentity.AddClaim(new Claim("TokenGuid", Guid.NewGuid().ToString()));
        var ticket = new AuthenticationTicket(oAuthIdentity, properties);
        await Startup.OAuthOptions.RefreshTokenProvider.CreateAsync(new AuthenticationTokenCreateContext(Request.GetOwinContext(), AccessTokenFormat, ticket));
        Authentication.SignIn(properties, oAuthIdentity);

Now all my tokens can be refreshed, because I passed TokenGuid to RefreshTokenProvider, after that I'm creating token with that GUID and next time I will refresh it /Token?grant_type=refresh_token.....

P.S. If you need detailed help you can write me.

like image 93
Andrian Durlestean Avatar answered Oct 22 '22 19:10

Andrian Durlestean


A few extra remarks:

  • If you're using the default accesstoken formats.
    • Remember to use for example: Startup.OAuthOptions.RefreshTokenFormat instead of Startup.OAuthOptions.AccessTokenFormat
    • Otherwise the decryptionstage will throw an exception
  • To get the refresh token in de response of the getexternallogin you have to add a override in: OAuthAuthorizationServerProvider
public override Task AuthorizationEndpointResponse(OAuthAuthorizationEndpointResponseContext context)
{
            var refreshToken = context.OwinContext.Authentication.AuthenticationResponseGrant.Properties.Dictionary["refresh_token"];

        if (!string.IsNullOrEmpty(refreshToken))
        {
            context.AdditionalResponseParameters.Add("refresh_token", refreshToken);
        }
        return base.AuthorizationEndpointResponse(context);
}
like image 32
Wouter Crooy Avatar answered Oct 22 '22 20:10

Wouter Crooy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!