Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Example of using ASP.NET Identity 2.0 UserManagerFactory with UseOAuthBearerTokens method?

The ASP.NET Identity 2.0 alpha ships with new middleware to manage getting an instance of the UserManager (app.UseUserManagerFactory to set this up) and getting an instance of the DbContext (app.UseDbContextFactory to set this up). There is an example showing how to get this working with an MVC app, but there is no documentation on how to get this working from the SPA template which uses OAuthBearerTokens, unlike the sample.

I currently am stuck with:

UserManagerFactory = () => new DerivedUserManager(new CustomUserStore(new CustomDbContext()));

OAuthOptions = new Microsoft.Owin.Security.OAuth.OAuthAuthorizationServerOptions
    {
            TokenEndpointPath = new PathString("/Token"),
            Provider = new MyApp.Web.Api.Providers.ApplicationOAuthProvider(PublicClientId, UserManagerFactory),
            AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
            AllowInsecureHttp = true
    };
app.UseOAuthBearerTokens(OAuthOptions);

and have no idea how to replace the UserManagerFactory above with calls like these from the 2.0 alpha samples while still working with the OAuthBearerTokens objects used in the SPA template:

        app.UseDbContextFactory(ApplicationDbContext.Create);

        // Configure the UserManager
        app.UseUserManagerFactory(new IdentityFactoryOptions<ApplicationUserManager>()
        {
            DataProtectionProvider = app.GetDataProtectionProvider(),
            Provider = new IdentityFactoryProvider<ApplicationUserManager>()
            {
                OnCreate = ApplicationUserManager.Create
            }
        });

Thanks... -Ben

like image 337
BenjiFB Avatar asked Feb 03 '14 03:02

BenjiFB


3 Answers

I am adding stubs here which show you how you can use OAuthBearerTokens... You do not have to use the UserManagerFactory that you were using in SPA. You can switch that to use the PerOWINContext pattern.

Startup.Auth.cs

app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

OAuthOptions = new OAuthAuthorizationServerOptions
{
    TokenEndpointPath = new PathString("/Token"),
    Provider = new ApplicationOAuthProvider(PublicClientId),
    AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
    AllowInsecureHttp = true
};

ApplicationOAuthProvider.cs

public ApplicationOAuthProvider(string publicClientId)
{
   if (publicClientId == null)
   {
       throw new ArgumentNullException("publicClientId");
   }
   _publicClientId = publicClientId;
}

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
   var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();

   ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);

   if (user == null)
   {
       context.SetError("invalid_grant", "The user name or password is incorrect.");
       return;
   }

   ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
               OAuthDefaults.AuthenticationType);
   ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager,
                DefaultAuthenticationTypes.ApplicationCookie);

   AuthenticationProperties properties = CreateProperties(user.UserName);
   AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
   context.Validated(ticket);
   context.Request.Context.Authentication.SignIn(cookiesIdentity); 
}

 

// namespace below needed to enable GetUserManager extension of the OwinContext
using Microsoft.AspNet.Identity.Owin;
like image 168
pranav rastogi Avatar answered Nov 16 '22 07:11

pranav rastogi


Some New Patterns with ASP.NET Identity 2.0

The ASP.NET Identity includes support for creating a single instance of a the UserManager and the identity DBContext per application request. To support this pattern use the following extension methods per the IAppBuilder object:

app.CreatePerOwinContext<AppUserIdentityDbContext>(AppUserIdentityDbContext.Create);
app.CreatePerOwinContext<AppUserManager>(AppUserManager.Create);

You can find a great example implementing this very pattern below:

ASP.NET Identity 2.0 Cookie & Token Authentication including a sample project.

Here is the AppManager Class:

public class AppUserManager : UserManager<AppUserIdentity>
{
    public AppUserManager(IUserStore<AppUserIdentity> store)
        : base(store) { }

    public static AppUserManager Create(IdentityFactoryOptions<AppUserManager> options, IOwinContext context)
    {
        var manager = new AppUserManager(new UserStore<AppUserIdentity>(context.Get<AppUserIdentityDbContext>()));
        return manager;
    }

}

This acticle uses the OWIN Middleware components UseOAuthBearerAuthentication and UseCookieAuthentication to support browser based authentication along with single Owin context IdentityDb Objects and a single AppManager.

Setup Bearer Tokens

Startup.Auth.cs

OAuthBearerOptions = new OAuthBearerAuthenticationOptions();

//This will used the HTTP header: "Authorization" Value: "Bearer 1234123412341234asdfasdfasdfasdf"
app.UseOAuthBearerAuthentication(OAuthBearerOptions);
// Enable the application to use a cookie to store information for the signed in user
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login")
}); 

HostAuthenticationFilter represents an authentication filter that authenticates via OWIN middleware:

WebApiConfig.cs

config.SuppressDefaultHostAuthentication();
//This will used the HTTP header: "Authorization" Value: "Bearer 1234123412341234asdfasdfasdfasdf"
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

To Generate a Token:

var identity = new ClaimsIdentity(Startup.OAuthBearerOptions.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, user));
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, userIdentity.Id));
AuthenticationTicket ticket = new AuthenticationTicket(identity, new AuthenticationProperties());
var currentUtc = new SystemClock().UtcNow;
ticket.Properties.IssuedUtc = currentUtc;
ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromMinutes(30));
string AccessToken = Startup.OAuthBearerOptions.AccessTokenFormat.Protect(ticket);
return AccessToken;
like image 26
hylander0 Avatar answered Nov 16 '22 07:11

hylander0


Ben, some of these things have changed from the alpha1 to beta1 builds (currently available on the ASP.NET Nightly NuGet Repo at https://aspnetwebstack.codeplex.com/wikipage?title=Use%20Nightly%20Builds). If you upgrade to the latest beta bits, you will not be using this syntax anymore but this instead:

// Configure the db context and user manager to use per request
app.CreatePerOwinContext(ApplicationIdentityContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

Also, notice that HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager> is now moved to Microsoft.AspNet.Identity.Owin.

You can install the `Microsoft.AspNet.Identity.Samples' package (preferably in a new MVC project because it might overwrite files). It helped me learn how they do certain things considering documentation for 2.0 is non-existent at the moment besides a few blog posts (all of which written for the alpha1 builds).

like image 5
Vesselin Obreshkov Avatar answered Nov 16 '22 07:11

Vesselin Obreshkov