Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simple Bearer Auth using OWIN Authentication

##Simple Bearer Auth using OWIN Authentication

Install

  1. Install the following packages: Microsoft.AspNet.WebApi.Owin, Microsoft.Owin.Security.OAuth, Microsoft.Owin.Host.SystemWeb (for hosting on IIS)
  2. Add the required models and appcontext
  3. Add helpers
  4. Add startup.cs

Testing

  1. Create a user account through the db or your own API
  2. Post the following raw data to /token username={username or email}&password={password as plaintext}&grant_type=password
  3. The response should contain an access_token.
  4. Add Header Authorization = bearer {access_token from previous step} and make a request to an Authorized controller.

Notes

This is a response to this StackOverflow question. This has not meant to scale or be used for anything more than super simple Web API authentication. Comments are welcome!

using EventTracker.Models;
using Microsoft.Owin.Security.OAuth;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Linq;
namespace EventTracker.Helpers {
public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider {
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) {
// OAuth2 supports the notion of client authentication
// this is not used here
context.Validated();
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) {
// validate user credentials (demo!)
// user credentials should be stored securely (salted, iterated, hashed yada)
var db = new AppContext();
var hashedPassword = context.Password.ToHash();
var user = db.Users.FirstOrDefault(u => (u.Email == context.UserName || u.Name == context.UserName) && u.Password == hashedPassword);
if (user == null) {
context.Rejected();
return;
}
// create identity
var id = new ClaimsIdentity(context.Options.AuthenticationType);
id.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
user.UserRoles.ToList().ForEach(ur=>{
id.AddClaim(new Claim(ClaimTypes.Role, ur.RoleId));
});
context.Validated(id);
}
}
}
namespace EventTracker.Helpers {
public static class Strings {
public static string ToHash(this string str) {
// Hash string using salt...
}
}
}
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Web;
namespace EventTracker.Models {
public class AppContext : DbContext {
public AppContext() : this("DefaultConnection") { }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
//Define relationships here using FluentApi
modelBuilder.Entity<UserRole>()
.HasKey(ur => new { ur.UserId, ur.RoleId });
modelBuilder.Entity<UserRole>()
.HasRequired<User>(ur => ur.User)
.WithMany(u => u.UserRoles)
.HasForeignKey(ur => ur.UserId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<UserRole>()
.HasRequired<Role>(ur => ur.Role)
.WithMany()
.HasForeignKey(ur => ur.RoleId)
.WillCascadeOnDelete(false);
}
#region DbSets
//Define Datasets here
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
public new IDbSet<T> Set<T>() where T : class {
return base.Set<T>();
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace EventTracker.Models {
public abstract class BaseEntity : IBaseEntity {
internal BaseEntity() {
if (string.IsNullOrEmpty(Id)) Id = Guid.NewGuid().ToString();
Created = DateTime.UtcNow;
}
public virtual string Id { get; set; }
public DateTime Created { get; set; }
public DateTime? Modified { get; set; }
public abstract void Delete(AppContext db);
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace EventTracker.Models {
public class Role : BaseEntity{
public Role() : base() {
}
public string Name { get; set; }
public override void Delete(AppContext db) {
var userRoles = db.Set<UserRole>();
userRoles.Where(ur => ur.RoleId == this.Id).ToList().ForEach(ur => userRoles.Remove(ur));
db.Roles.Remove(this);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace EventTracker.Models{
public class User : BaseEntity {
public User () : base() {
UserRoles = new HashSet<UserRole>();
}
public string Name { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public virtual ICollection<UserRole> UserRoles { get; set; }
public override void Delete(AppContext db) {
UserRoles.Clear();
db.Users.Remove(this);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace EventTracker.Models {
public class UserRole {
public UserRole() { }
public UserRole(string UserId, string RoleId) {
this.UserId = UserId;
this.RoleId = RoleId;
}
public UserRole(User User, Role Role) : this(User.Id, Role.Id) { }
public string UserId { get; set; }
public virtual User User { get; set; }
public string RoleId { get; set; }
public virtual Role Role { get; set; }
}
}
using EventTracker.Helpers;
using Microsoft.Owin;
using Microsoft.Owin.Security.OAuth;
using Owin;
using System;
[assembly: OwinStartup(typeof(EventTracker.Startup))]
namespace EventTracker {
public class Startup {
public void Configuration(IAppBuilder app) {
// token generation
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions {
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromHours(8),
Provider = new SimpleAuthorizationServerProvider()
});
// token consumption
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
}
@flo-rider

This comment has been minimized.

Copy link

@flo-rider flo-rider commented Jul 5, 2015

This may seem exactly what I need: I'm not using asp.net identity, but the old aspnet_membership tables. I want my existing users to be able to login with their username/password (which are stored in my DB) via oAuth...is that what your code does? It serves as its own oAuth authorization server?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment