With this code:
MyAuthorizationServerProvider
public class MyAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated(); //
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
if (context.UserName == "admin" && context.Password == "admin")
{
identity.AddClaim(new Claim(ClaimTypes.Role, "admin"));
identity.AddClaim(new Claim("username", "admin"));
identity.AddClaim(new Claim(ClaimTypes.Name, "Juan Dela Cruz"));
context.Validated(identity);
}
else if (context.UserName == "user" && context.Password == "user")
{
identity.AddClaim(new Claim(ClaimTypes.Role, "user"));
identity.AddClaim(new Claim("username", "user"));
identity.AddClaim(new Claim(ClaimTypes.Name, "Barok Kabundukan"));
context.Validated(identity);
}
else
{
context.SetError("invalid_grant", "Provided username or password is incorrect");
return;
}
}
}
AuthorizeAttribute
protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (!HttpContext.Current.User.Identity.IsAuthenticated)
{
base.HandleUnauthorizedRequest(actionContext);
}
else
{
actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Forbidden);
}
}
Startup
public class Startup
{
public void Configuration(IAppBuilder app)
{
//enable cors origin requests
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
var myProvider = new MyAuthorizationServerProvider();
OAuthAuthorizationServerOptions options = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = myProvider
};
app.UseOAuthAuthorizationServer(options);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
}
}
DataController
public class DataController : ApiController
{
[AllowAnonymous]
[HttpGet]
[Route("api/data/forall")]
public IHttpActionResult Get()
{
return Ok("Server time is: " + DateTime.Now);
}
[Authorize]
[HttpGet]
[Route("api/data/authenticate")]
public IHttpActionResult GetForAuthenticate()
{
var identity = (ClaimsIdentity)User.Identity;
return Ok("Hello " + identity.Name);
}
[Authorize(Roles = "admin")]
[HttpGet]
[Route("api/data/authorize")]
public IHttpActionResult GetForAdmin()
{
var identity = (ClaimsIdentity)User.Identity;
var roles = identity.Claims
.Where(c => c.Type == ClaimTypes.Role)
.Select(c => c.Value);
return Ok("Hello " + identity.Name + " Role: " + string.Join(",", roles.ToList()));
}
}
With that code, I am able to get the token and authenticate. The problem however is when I use the "user" credentials and authenticate then access the method that has Authorize(Role="admin"), in the Postman, I get "401". I should be getting the "403" since I am authenticated already but do not have a role of "admin". Can you please show me where I am getting it wrong? Thank you.
No, you should still get 401. 401 means unauthorized, not unauthenticated. In your scenario, you do not have the admin role, so you are not authorized to access the requested resource.
EDIT:
I don't usually post Wikipedia, but I think the article on 403 explains this pretty well; see the section on the differences between 401 and 403:
https://en.wikipedia.org/wiki/HTTP_403
Related
The method has been secured with roles=admin:
[Authorize(Roles = "admin")]
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}}
I am successfully to use claims with Webapi project where Individual User Account is selected where the claim admin is injected in
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
// Add custom user claims here
userIdentity.AddClaim(new Claim(ClaimTypes.Role, "admin"));
return userIdentity;
}
}
Now I want to test with Windows authentication option where a IAuthenticationFilter is implemented:
public class CustomAuthenticationFilter : IAuthenticationFilter
{
public bool AllowMultiple { get { return true; } }
public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
var windowsPrincipal = context.Principal as WindowsPrincipal;
if (windowsPrincipal != null)
{
var name = windowsPrincipal.Identity.Name;
// TODO: fetch claims from db (i guess based on name)
var identity = new ClaimsIdentity(windowsPrincipal.Identity);
identity.AddClaim(new Claim(ClaimTypes.Role, "admin"));
var claimsPrincipal = new ClaimsPrincipal(identity);
// here is the punchline - we're replacing original windows principal
// with our own claims principal
context.Principal = claimsPrincipal;
}
return Task.FromResult(0);
}
public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
{
return Task.FromResult(0);
}
}
and added to class webapiconfig:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.Filters.Add(new CustomAuthenticationFilter());
...
}
}
The claim admin is in User.Identity.Claims when debugging webapi project, however it could not be authorized in method /api/values/get.
Any idea?
The default identity RoleClaimType is identity/claims/groupsid which is not role.
By setting RoleClaimType to identity/claims/role in the ClaimsIdentity constructor, we can get it passing [Authorize(Roles = "admin")]
public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
var windowsPrincipal = context.Principal as WindowsPrincipal;
if (windowsPrincipal != null)
{
var name = windowsPrincipal.Identity.Name;
// TODO: fetch claims from db (i guess based on name)
var identity = new ClaimsIdentity(windowsPrincipal.Identity,
null,
"Negotiate",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/role");
//identity
identity.AddClaim(new Claim(ClaimTypes.Role, "admin"));
var claimsPrincipal = new ClaimsPrincipal(identity);
// here is the punchline - we're replacing original windows principal
// with our own claims principal
context.Principal = claimsPrincipal;
}
return Task.FromResult(0);
}
Here is the new identity:
I have a hub that does not convert the token located at Authorization:Bearer eyjsdalfsadlfjffdafs... in the request header to an identity. The rest of the API works fine with standard http verbs however for some reason SignalR is not authorizing the token into a user.
public class ChatHub : Hub
{
[Authorize]
public override Task OnConnected()
{
// error context.user.identity.name =""
var userId = int.Parse(Context.User.Identity.Name);
return base.OnConnected();
}
....
}
Startup.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
JwtHandler - this part of the filter is not called when the client connects to the hub even though onConnect() is attributed with [Authorize]
public class JwtHandler : DelegatingHandler
{
private const string ISSUER = "Issuer";
private const string AUDIENCE = "Audience";
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
byte[] key = Convert.FromBase64String("SecretKey");
try
{
var headers = request.Headers;
if(headers.Authorization != null)
{
if(headers.Authorization.Scheme.Equals("Bearer"))
{
string jwt = request.Headers.Authorization.Parameter;
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
TokenValidationParameters parms = new TokenValidationParameters()
{
ValidAudience = AUDIENCE,
ValidIssuers = new List<string>(){ISSUER},
IssuerSigningToken = new BinarySecretSecurityToken(key),
};
SecurityToken validated = new JwtSecurityToken(jwt);
var principal = tokenHandler.ValidateToken(jwt, parms,out validated);
Thread.CurrentPrincipal = principal;
if(HttpContext.Current !=null)
{
HttpContext.Current.User = principal;
}
}
}
var response = await base.SendAsync(request, cancellationToken);
if(response.StatusCode == HttpStatusCode.Unauthorized)
{
response.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue("Bearer", "error=\"invalid_token\""));
return response;
}
return response;
}catch (Exception)
{
var response = request.CreateResponse(HttpStatusCode.Unauthorized);
response.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue("Bearer", "error=\"invalid_token\""));
return response;
}
}
}
Try validating the jwt token in the OWIN middleware. In your Startup.cs add:
public void Configuration(IAppBuilder app)
{
app.UseJwtBearerAuthentication(
new Microsoft.Owin.Security.Jwt.JwtBearerAuthenticationOptions() {
AllowedAudiences = new string[] { ALLOWEDAUDIENCE },
IssuerSecurityTokenProviders = new[] {
new SymmetricKeyIssuerSecurityTokenProvider(ISSUER, System.Convert.FromBase64String(cKey))
}
});
app.MapSignalR();
}
I've implemented OAuth authentication in my Web Api project based on these blog posts
It works well, including the refresh token logic.
I want to add an option for basic authentication as well for a couple of calls for scheduled jobs.
I've tried adding a Basic Auth solution as middleware but I'm still getting 401 asking for the Bearer token.
I can get it to work by removing the [Authorize] attribute from those api calls and checking manually in code if the user is authenticated but seems like the wrong way to solve it.
Is there a way to support both Basic Auth and OAuth authentication using OWin?
How about you attribute your actions or controller with you want to implement Basic authentication with the attribute [OverrideAuthentication] Then you create custom authentication filter attribute which inherits from Attribute, IAuthenticationFilter as the code below
public class BasicAuthenticationAttribute : Attribute, IAuthenticationFilter
{
public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
var req = context.Request;
// Get credential from the Authorization header
//(if present) and authenticate
if (req.Headers.Authorization != null && "basic".Equals(req.Headers.Authorization.Scheme, StringComparison.OrdinalIgnoreCase))
{
var rawCreds = req.Headers.Authorization.Parameter;
var credArray = GetCredentials(rawCreds);
var clientId = credArray[0];
var secret = credArray[1];
if (ValidCredentials(clientId, secret))
{
var claims = new List<Claim>()
{
new Claim(ClaimTypes.Name, clientId)
};
var identity = new ClaimsIdentity(claims, "Basic");
var principal = new ClaimsPrincipal(new[] { identity });
// The request message contains valid credential
context.Principal = principal;
}
else
{
context.ErrorResult = new UnauthorizedResult(new AuthenticationHeaderValue[0], context.Request);
}
}
else
{
context.ErrorResult = new UnauthorizedResult(new AuthenticationHeaderValue[0], context.Request);
}
return Task.FromResult(0);
}
private string[] GetCredentials(string rawCred)
{
var encoding = Encoding.GetEncoding("UTF-8");
var cred = encoding.GetString(Convert.FromBase64String(rawCred));
var credArray = cred.Split(':');
if (credArray.Length == 2)
{
return credArray;
}
else
{
return credArray = ":".Split(':');
}
}
private bool ValidCredentials(string clientId, string secret)
{
//compare the values from web.config
if (clientId == secret)
{
return true;
}
return false;
}
public Task ChallengeAsync(HttpAuthenticationChallengeContext context,CancellationToken cancellationToken)
{
context.Result = new ResultWithChallenge(context.Result);
return Task.FromResult(0);
}
public class ResultWithChallenge : IHttpActionResult
{
private readonly IHttpActionResult next;
public ResultWithChallenge(IHttpActionResult next)
{
this.next = next;
}
public async Task<HttpResponseMessage> ExecuteAsync( CancellationToken cancellationToken)
{
var response = await next.ExecuteAsync(cancellationToken);
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
response.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue("Basic"));
}
return response;
}
}
public bool AllowMultiple
{
get { return false; }
}
}
Now you use it to attribute you controllers or actions as the code below:
[OverrideAuthentication]
[BasicAuthentication]
[Route("")]
public async Task<IHttpActionResult> Get()
{
}
Notice how we are creating claims identity and setting the Authentication scheme to Basic, you can put any claims you want here.
I am developing an Asp.net web Api 2 project and I am using OAuth. Now I am able to generate token and send it to client. Now how I will send that token to server from client using jQuery ajax call and validated that token explicitly and get user information. I am not using asp.net identity.
Code
public class UserModel
{
public string UserName { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
}
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
ConfigureOAuth(app);
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
}
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider()
};
// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
// Resource owner password credentials does not provide a client ID.
if (context.ClientId == null)
{
context.Validated();
}
return Task.FromResult<object>(null);
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
using (AuthRepository _repo = new AuthRepository())
{
var user = _repo.FindUser(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
}
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim("role", "user"));
context.Validated(identity);
}
}
You do not need and should not validate the token manually, just attribute you protected API end point with [Authorize] attribute and leave this validation to the framework, if the token is invalid or expired Web API will return 401 and your are good to go.
Regarding sending your obtained token from client application the server, you need to send the token in the Authorization header for your request with Bearer scheme Authorization: Bearer xf7jsjaaa9292....
Something like the below will help
beforeSend: function (xhr) {
xhr.setRequestHeader ("Authorization", "Bearer YOUR_TOKEN_GOES_HERE");
}
So you can use jQuery beforeSend callback to add an HTTP Authorization header.
Btw I guess the sample code is from my blog http://bitoftech.net so feel free to remove the below claims as it is not useful for your case:
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim("role", "user"));
And replace it with this one:
identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
I have an existing ASP.NET MVC 5 project and I'm adding a Web API 2 project to it. I want to use bearer token authentication and have followed Hongye Sun's tutorial "OWIN Bearer Token Authentication with Web API Sample" and this question as well.
In my Login method, for the line Startup.OAuthBearerOptions.AccessTokenFormat.Protect(ticket);, the AccessTokenFormat is null. Any idea why?
My AccountController:
[RoutePrefix("api")]
public class AccountController : ApiController
{
public AccountController() {}
// POST api/login
[HttpPost]
[Route("login")]
public HttpResponseMessage Login(int id, string pwd)
{
if (id > 0) // testing - not authenticating right now
{
var identity = new ClaimsIdentity(Startup.OAuthBearerOptions.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, id.ToString()));
AuthenticationTicket ticket = new AuthenticationTicket(identity, new AuthenticationProperties());
var currentUtc = new SystemClock().UtcNow;
ticket.Properties.IssuedUtc = currentUtc;
ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromMinutes(30));
var token = Startup.OAuthBearerOptions.AccessTokenFormat.Protect(ticket);
return new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ObjectContent<object>(new
{
UserName = id.ToString(),
AccessToken = token
}, Configuration.Formatters.JsonFormatter)
};
}
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
// POST api/token
[Route("token")]
[HttpPost]
public HttpResponseMessage Token(int id, string pwd)
{
// Never reaches here. Do I need this method?
return new HttpResponseMessage(HttpStatusCode.OK);
}
}
Startup class:
public class Startup
{
private static readonly ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
public static Func<MyUserManager> UserManagerFactory { get; set; }
public static string PublicClientId { get; private set; }
static Startup()
{
PublicClientId = "MyWeb";
UserManagerFactory = () => new MyUserManager(new UserStore<MyIdentityUser>());
OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/api/token"),
Provider = new MyWebOAuthProvider(PublicClientId, UserManagerFactory),
AuthorizeEndpointPath = new PathString("/api/login"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = true
};
}
public void Configuration(IAppBuilder app)
{
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/api/login")
});
// Configure Web API to use only bearer token authentication.
var config = GlobalConfiguration.Configuration;
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthBearerOptions.AuthenticationType));
app.UseWebApi(config);
}
}
MyIdentityUser just adds an extra property:
public class MyIdentityUser : IdentityUser
{
public int SecurityLevel { get; set; }
}
MyUserManager calls my custom user authentication method to an internal server:
public class MyUserManager : UserManager<MyIdentityUser>
{
public MyUserManager(IUserStore<MyIdentityUser> store) : base(store) { }
public MyIdentityUser ValidateUser(int id, string pwd)
{
LoginIdentityUser user = null;
if (MyApplication.ValidateUser(id, pwd))
{
// user = ??? - not yet implemented
}
return user;
}
}
MyWebOAuthProvider (I took this from the SPA template. Only GrantResourceOwnerCredentials has been changed):
public class MyWebOAuthProvider : OAuthAuthorizationServerProvider
{
private readonly string _publicClientId;
private readonly Func<MyUserManager> _userManagerFactory;
public MyWebOAuthProvider(string publicClientId, Func<MyUserManager> userManagerFactory)
{
if (publicClientId == null)
{
throw new ArgumentNullException("publicClientId");
}
if (userManagerFactory == null)
{
throw new ArgumentNullException("userManagerFactory");
}
_publicClientId = publicClientId;
_userManagerFactory = userManagerFactory;
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
using (MyUserManager userManager = _userManagerFactory())
{
MyIdentityUser user = null;
var ctx = context as MyWebOAuthGrantResourceOwnerCredentialsContext;
if (ctx != null)
{
user = userManager.ValidateUser(ctx.Id, ctx.Pwd);
}
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
ClaimsIdentity oAuthIdentity = await userManager.CreateIdentityAsync(user,
context.Options.AuthenticationType);
ClaimsIdentity cookiesIdentity = await userManager.CreateIdentityAsync(user,
CookieAuthenticationDefaults.AuthenticationType);
AuthenticationProperties properties = CreateProperties(user.UserName);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(cookiesIdentity);
}
}
public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
... // unchanged from SPA template
}
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
... // unchanged from SPA template
}
public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
{
... // unchanged from SPA template
}
public static AuthenticationProperties CreateProperties(string userName)
{
... // unchanged from SPA template
}
}
MyWebOAuthGrantResourceOwnerCredientialsContext:
public class MyWebOAuthGrantResourceOwnerCredentialsContext : OAuthGrantResourceOwnerCredentialsContext
{
public MyWebOAuthGrantResourceOwnerCredentialsContext (IOwinContext context, OAuthAuthorizationServerOptions options, string clientId, string userName, string password, IList<string> scope)
: base(context, options, clientId, userName, password, scope)
{ }
public int Id { get; set; }
public string Pwd { get; set; }
}
How is AccessTokenFormat set? Is what I've set up correct? I'm not authenticating against any external services, just a legacy internal server.
Thanks.
I had the same problem - it was to do with my initialisation in Startup().
Like you, I was storing the OAuthBearerOptions in a static field:
OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
But then I was wrongly using a new instance of the same class later on:
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); // wrong!
Obviously the fix was to use the static field instead:
app.UseOAuthBearerAuthentication(OAuthBearerOptions);
In fact, it doesn't look like you call UseOAuthBearerAuthentication() at all. I followed this excellent series of posts by Taiseer Joudeh.
Full Startup.cs:
public class Startup
{
public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
ConfigureOAuth(app);
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
public void ConfigureOAuth(IAppBuilder app)
{
//use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseExternalSignInCookie(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ExternalCookie);
OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions() {
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider() // see post
};
// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(OAuthBearerOptions);
//[Configure External Logins...]
}
}
I'm not sure if you're still looking for the answer to this - but here's a bit of code that I'm using in my AngularJS app to get the security token from my WebAPI2 endpoint.
$http({
method: 'POST', url: '/token', data: { username: uName, password: uPassword, grant_type: 'password' },
transformRequest: function (obj) {
var str = [];
for (var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
}
}).success(function (data, status, headers, config) {
console.log("http success", data);
accessToken.value = data.access_token;
console.log("access token = ", accessToken.value);
}).error(function (data, status, headers, config) {
console.log("http error", data);
});
I can then pass the accessToken in the header of any other requests in order to get the authentication validation.
I have removed the sample code as it can cause confusion when it's used with Web API and SPA template. You'd better stay with the template code to use OAuth authorization server to generate token. In your scenario, you should use resource owner password grant to authenticate the user. Please check my blog on SPA template which has details about the password flow on http://blogs.msdn.com/b/webdev/archive/2013/09/20/understanding-security-features-in-spa-template.aspx
Instead of writing your own Web API to handle login, you need to use OWIN OAuth Server's /token endpoint to handle password login.