SignalR authentication failed when passing "Bearer" through query string - angularjs

I'd like to enable authentication in SignalR while the server was hosted in ASP.NET WebAPI which I'm using OAuth Bearer authrntication and the client is AngularJS.
On client side I originally pass the Bearer token through HTTP header and it works well with the WebAPI. But since SignalR JavsScript doesn't support adding HTTP headers in connection (it's because WebSocket doesn't support specifying HTTP headers) I need to pass the Bearer token through query string by using the code like self.connection.qs = { Bearer: 'xxxxxx' };
The problem is on the WebAPI side my SignalR always returned 401 Unauthorized.
Below is what I did on the WebAPI side.
1, I specified OAuthBearerAuthenticationOptions.Provider to QueryStringEnabledOAuthBearerAuthenticationProvider, which is a class I created inherited from OAuthBearerAuthenticationProvider that can retrieve Bearer token from query string. Code as below.
public class QueryStringEnabledOAuthBearerAuthenticationProvider : OAuthBearerAuthenticationProvider
{
private readonly string _name;
public QueryStringEnabledOAuthBearerAuthenticationProvider()
: this(OAuthDefaults.AuthenticationType)
{
}
public QueryStringEnabledOAuthBearerAuthenticationProvider(string name)
{
_name = name;
}
public override Task RequestToken(OAuthRequestTokenContext context)
{
// try to read token from base class (header) if possible
base.RequestToken(context).Wait();
if (string.IsNullOrWhiteSpace(context.Token))
{
// try to read token from query string
var token = context.Request.Query.Get(_name);
if (!string.IsNullOrWhiteSpace(token))
{
context.Token = token;
}
}
return Task.FromResult(null);
}
}
And registered it as below while WebAPI was started.
var options = new OAuthBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AuthenticationType = AuthenticationType,
Provider = new QueryStringEnabledOAuthBearerAuthenticationProvider(),
AccessTokenFormat = _accessTokenFormat,
};
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
app.UseOAuthBearerAuthentication(options);
2, In SignalR part I created an authorize attribute as below. Nothing changed just to be used to add break point.
public class BearerAuthorizeAttribute : AuthorizeAttribute
{
public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request)
{
return base.AuthorizeHubConnection(hubDescriptor, request);
}
public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod)
{
return base.AuthorizeHubMethodInvocation(hubIncomingInvokerContext, appliesToMethod);
}
}
And registered it when WebAPI started as well.
app.Map("/signalr", map =>
{
// Setup the CORS middleware to run before SignalR.
// By default this will allow all origins. You can
// configure the set of origins and/or http verbs by
// providing a cors options with a different policy.
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
// You can enable JSONP by uncommenting line below.
// JSONP requests are insecure but some older browsers (and some
// versions of IE) require JSONP to work cross domain
// EnableJSONP = true
EnableJavaScriptProxies = false
};
// Run the SignalR pipeline. We're not using MapSignalR
// since this branch already runs under the "/signalr"
// path.
map.RunSignalR(hubConfiguration);
// Require authentication for all hubs
var authorizer = new BearerAuthorizeAttribute();
var module = new AuthorizeModule(authorizer, authorizer);
GlobalHost.HubPipeline.AddModule(module);
});
I found, when SignalR connected my QueryStringEnabledOAuthBearerAuthenticationProvider.RequestToken was invoked and it retrieved Bearer token successfully. But then when SignalR BearerAuthorizeAttribute.AuthorizeHubConnection was invoked the parameter request.User still not authenticated. So it returned 401.
Can anyone give me some ideas on what's wrong I did, thanks.

I'm using headers, this is how I solved it
var authData = localStorageService.get('authorizationData');
var token = authData.token;
$.signalR.ajaxDefaults.headers = { Authorization: "Bearer " + token };
Hope it helps

I resolved this problem by unprotect the Bearer token from query string in my AuthorizeAttribute, and set the user principal into a new ServerRequest. For detailed information please check http://blog.shaunxu.me/archive/2014/05/27/set-context-user-principal-for-customized-authentication-in-signalr.aspx
This might not be the best solution but it worked.

Related

JSESSIONID changing every time API Fires. if same then CORS POLICY issue

So here is the Problem.
Front end: React Js
Backend: Spring Boot (No .xml file only annotation and properties files)
What I did is first user have to login then only he can access other APIs
when user login:
#PostMapping("/signin")
public boolean signIn(HttpServletRequest request, #Valid #RequestBody UserCredentials loginData) {
return userCredentials.signInToAccount(request, loginData);
}
It will goes to this file and then it calls service class
#Override
public boolean signInToAccount(HttpServletRequest request, UserCredentials loginData) {
UserCredentials user;
HttpSession session;
try {
user = userDAO.findById(loginData.getAssociateId()).get();
} catch (NoSuchElementException e) {
logger.error(e.getMessage());
throw new NoSuchElementException(env.getProperty("signin.invalidId.error"));
}
if (user.getPassword().equals(loginData.getPassword())
&& user.getIsAssociateActive().equals(env.getProperty("active.yes"))) {
session = request.getSession(true);
session.setAttribute(env.getProperty("session.attribute"), loginData.getAssociateId());
return true;
} else {
return false;
}
}
Here I am setting the session with logged user id:
Now When I try to use any APIs like
#GetMapping("/my-tasks")
public List<Task> getAllTaskInfo(HttpServletRequest request) throws UserNotLoggedInException {
String id = session.getSessionAttributeValue(request);
return taskServices.getAllTasksDetail(id);
}
It called the session to get the id if session is not created then User Define Exception is thrown.
Here is my session file:
public String getSessionAttributeValue(HttpServletRequest request) throws UserNotLoggedInException {
String loginFirst = "";
try {
HttpSession session = request.getSession();
loginFirst = properties.getPropertyObject("session.notlogin");
return session.getAttribute(properties.getPropertyObject("session.attribute")).toString();
} catch (Exception e) {
throw new UserNotLoggedInException(loginFirst);
}
}
With Postman it is working fine.
But for Browser(edge,chrome) its nt working.
What I tried:
I tried to debug I found that with postman cookies stored with same id after login but with browser JSESSIONID is changed every time its called for APIs.
Please help me.
Thanking you in advance.
EDIT 1:
I used withCredentials:true in my api call like this
axios.post(BASE_URL_USER + "/signin", credentials,{withCredentials:true});
But now Facing CORS error
Access to XMLHttpRequest at 'http://localhost:9090/signin' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
I tried to remove the #CrossOrigin("*") to #CrossOrigin(origin="http://localhost:3000") or #CrossOrigin(origin="http://localhost:9090")
but not working
I have not applied any security filter or configuration in my backend and neither any header or cors nothing in frontend .
Just a normal call from frontend to backend.
Note: it is working perfectly with POSTMAN.

API cookie problems - trying to create XSRF/CSRF token in angular

My Web API method for initializing a session is successfully returning a cookie. The front end is in angular so I'm calling the cookie XSRF-TOKEN because angular says it will take that and turn it into a header called X-XSRF-TOKEN in all subsequent requests.
For reference the Web API GET controller method that creates the cookie looks like
...
HttpResponseMessage resp = new HttpResponseMessage() {
Content = new JsonContent(results)
};
if (results.Token != null) {
var cookie = new CookieHeaderValue("XSRF-TOKEN", results.Token);
cookie.Expires = DateTimeOffset.Now.AddDays(365);
cookie.Domain = Request.RequestUri.Host;
cookie.Path = "/";
cookie.HttpOnly = false;
resp.Headers.AddCookies(new CookieHeaderValue[] { cookie });
}
return resp;
...
Using Fiddler I can see the cookie in the response. Now I'm expecting 2 things
all subsequent API calls to that same domain should include this cookie in the request header
Angular should be adding the X-XSRF-TOKEN header I mentioned earlier
Neither one is happening (I'm checking with Fiddler). I've tried with the site and API in the same domain (like localhost) and in different domains.
Some sources I've checked:
https://docs.angularjs.org/api/ng/service/$http
https://stormpath.com/blog/angular-xsrf
I also tried adding
$httpProvider.xsrfWhitelistedOrigins = [webServicesPath];
where webServicesPath is a variable I use for the API path but it makes no difference.
You should use something like following
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery) {
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false });
}
public void ConfigureServices(IServiceCollection services) {
// Angular's default header name for sending the XSRF token.
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
}

Asp.net core token based claims authentication with OpenIdConnect and angularjs: Bearer was forbidden

I'm using Asp.net core rc2 with OpenIdConnectServer. I'm using angular 1.x with augular-oauth2. After a few days, my error has digressed to
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:54275/api/Account/Username
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: Successfully validated the token.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: HttpContext.User merged via AutomaticAuthentication from authenticationScheme: Bearer.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: AuthenticationScheme: Bearer was successfully authenticated.
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed for user: .
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Warning: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes (Bearer).
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: AuthenticationScheme: Bearer was forbidden.
My ConfigureServices consists of
services.AddAuthorization(options =>
{
options.AddPolicy("UsersOnly", policy =>
{
policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
policy.RequireClaim("role");
});
});
My configure has
app.UseWhen(context => context.Request.Path.StartsWithSegments(new PathString("/api")), branch =>
{
branch.UseJwtBearerAuthentication(new JwtBearerOptions
{
AutomaticAuthenticate = true,
AutomaticChallenge = true,
RequireHttpsMetadata = false,
Audience = "http://localhost:54275/",
Authority = "http://localhost:54275/",
TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = "client1",
//ValidAudiences = new List<string> { "", "empty", "null"}
}
});
});
app.UseOpenIdConnectServer(options =>
{
options.AuthenticationScheme = OpenIdConnectServerDefaults.AuthenticationScheme;
options.Provider = new SimpleAuthorizationServerProvider();
options.AccessTokenHandler = new JwtSecurityTokenHandler();
options.ApplicationCanDisplayErrors = true;
options.AllowInsecureHttp = true;
options.TokenEndpointPath = new PathString("/oauth2/token");
options.LogoutEndpointPath = new PathString("/oauth2/logout");
options.RevocationEndpointPath = new PathString("/oauth2/revoke");
options.UseJwtTokens();
//options.AccessTokenLifetime = TimeSpan.FromHours(1);
});
My authorize attribute is defined on the Controller as
[Authorize(Policy = "UsersOnly", ActiveAuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme), Route("api/Account")]
I store the token as a cookie and attach it to requests using an http interceptor in angular.
I generate the token with
public override async Task GrantResourceOwnerCredentials(GrantResourceOwnerCredentialsContext context)
{
// validate user credentials (demo mode)
// should be stored securely (salted, hashed, iterated)
using (var con = new SqlConnection(ConnectionManager.GetDefaultConnectionString()))
{
if (!Hashing.ValidatePassword(context.Password, await con.ExecuteScalarAsync<string>("SELECT PassHash FROM dbo.Users WHERE Username = #UserName", new { context.UserName })))
{
context.Reject(
error: "bad_userpass",
description: "UserName/Password combination was invalid."
);
return;
}
// create identity
var id = new ClaimsIdentity(context.Options.AuthenticationScheme);
id.AddClaim(new Claim("sub", context.UserName));
id.AddClaim(new Claim("role", "user"));
// create metadata to pass on to refresh token provider
var props = new AuthenticationProperties(new Dictionary<string, string>
{
{"as:client_id", context.ClientId}
});
var ticket = new AuthenticationTicket(new ClaimsPrincipal(id), props,
context.Options.AuthenticationScheme);
ticket.SetAudiences("client1");
//ticket.SetScopes(OpenIdConnectConstants.Scopes.OpenId, OpenIdConnectConstants.Scopes.Email, OpenIdConnectConstants.Scopes.Profile, "api-resource-controller");
context.Validate(ticket);
}
}
I've spent the last three days on this problem and I realize that at this point I'm probably missing something obvious due to lack of sleep. Any help would be appreciated.
The error you're seeing is likely caused by 2 factors:
You're not attaching an explicit destination to your custom role claim so it will never be serialized in the access token. You can find more information about this security feature on this other SO post.
policy.RequireClaim("role"); might not work OTB, as IdentityModel uses an internal mapping that converts well-known JWT claims to their ClaimTypes equivalent: here, role will be likely replaced by http://schemas.microsoft.com/ws/2008/06/identity/claims/role (ClaimTypes.Role). I'd recommend using policy.RequireRole("user") instead.
It's also worth noting that manually storing the client_id is not necessary as it's already done for you by the OpenID Connect server middleware.
You can retrieve it using ticket.GetPresenters(), that returns the list of authorized presenters (here, the client identifier). Note that it also automatically ensures a refresh token issued to a client A can't be used by a client B, so you don't have to do this check in your own code.

Redirect to Identity Server Login page from AngularJs http web api request

I am trying to redirect to Identity Server's default login page when calling an API controller method from Angular's $http service.
My web project and Identity Server are in different projects and have different Startup.cs files.
The web project Statup.cs is as follows
public class Startup
{
public void Configuration(IAppBuilder app)
{
AntiForgeryConfig.UniqueClaimTypeIdentifier = Thinktecture.IdentityServer.Core.Constants.ClaimTypes.Subject;
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies",
});
var openIdConfig = new OpenIdConnectAuthenticationOptions
{
Authority = "https://localhost:44301/identity",
ClientId = "baseballStats",
Scope = "openid profile roles baseballStatsApi",
RedirectUri = "https://localhost:44300/",
ResponseType = "id_token token",
SignInAsAuthenticationType = "Cookies",
UseTokenLifetime = false,
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = async n =>
{
var userInfoClient = new UserInfoClient(
new Uri(n.Options.Authority + "/connect/userinfo"),
n.ProtocolMessage.AccessToken);
var userInfo = await userInfoClient.GetAsync();
// create new identity and set name and role claim type
var nid = new ClaimsIdentity(
n.AuthenticationTicket.Identity.AuthenticationType,
Thinktecture.IdentityServer.Core.Constants.ClaimTypes.GivenName,
Thinktecture.IdentityServer.Core.Constants.ClaimTypes.Role);
userInfo.Claims.ToList().ForEach(c => nid.AddClaim(new Claim(c.Item1, c.Item2)));
// keep the id_token for logout
nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
// add access token for sample API
nid.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken));
// keep track of access token expiration
nid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString()));
// add some other app specific claim
nid.AddClaim(new Claim("app_specific", "some data"));
n.AuthenticationTicket = new AuthenticationTicket(
nid,
n.AuthenticationTicket.Properties);
n.Request.Headers.SetValues("Authorization ", new string[] { "Bearer ", n.ProtocolMessage.AccessToken });
}
}
};
app.UseOpenIdConnectAuthentication(openIdConfig);
app.UseResourceAuthorization(new AuthorizationManager());
app.Map("/api", inner =>
{
var bearerTokenOptions = new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "https://localhost:44301/identity",
RequiredScopes = new[] { "baseballStatsApi" }
};
inner.UseIdentityServerBearerTokenAuthentication(bearerTokenOptions);
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
inner.UseWebApi(config);
});
}
}
You will notice that the API is secured with bearer token authentication, whereas the rest of the app uses OpenIdConnect.
The Identity Server Startup.cs class is
public class Startup
{
public void Configuration(IAppBuilder app)
{
var policy = new System.Web.Cors.CorsPolicy
{
AllowAnyOrigin = true,
AllowAnyHeader = true,
AllowAnyMethod = true,
SupportsCredentials = true
};
policy.ExposedHeaders.Add("Location");
app.UseCors(new CorsOptions
{
PolicyProvider = new CorsPolicyProvider
{
PolicyResolver = context => Task.FromResult(policy)
}
});
app.Map("/identity", idsrvApp =>
{
idsrvApp.UseIdentityServer(new IdentityServerOptions
{
SiteName = "Embedded IdentityServer",
SigningCertificate = LoadCertificate(),
Factory = InMemoryFactory.Create(
users: Users.Get(),
clients: Clients.Get(),
scopes: Scopes.Get())
});
});
}
X509Certificate2 LoadCertificate()
{
return new X509Certificate2(
string.Format(#"{0}\bin\Configuration\idsrv3test.pfx", AppDomain.CurrentDomain.BaseDirectory), "idsrv3test");
}
}
Notice that I have added a CorsPolicy entry in order to allow the Web App to hopefully redirect to the Login page. In addition, the Cors policy exposes the Location request header, since it contains the url that I would like to redirect to.
The Web Api controller method is secured using the Authorize Attribute, like so
[HttpPost]
[EnableCors(origins: "*", headers: "*", methods: "*")]
[Authorize]
public PlayerData GetFilteredPlayers(PlayerInformationParameters parameters)
{
var playerInformation = composer.Compose<PlayerInformation>().UsingParameters(parameters);
var players = playerInformation.Players
.Select(p => new {
p.NameLast,
p.NameFirst,
p.Nickname,
p.BirthCity,
p.BirthState,
p.BirthCountry,
p.BirthDay,
p.BirthMonth,
p.BirthYear,
p.Weight,
p.Height,
p.College,
p.Bats,
p.Throws,
p.Debut,
p.FinalGame
});
var playerData = new PlayerData { Players = players, Count = playerInformation.Count, Headers = GetHeaders(players) };
return playerData;
}
The angular factory makes a call to $http, as shown below
baseballApp.factory('playerService', function ($http, $q) {
return {
getPlayerList: function (queryParameters) {
var deferred = $q.defer();
$http.post('api/pitchingstats/GetFilteredPlayers', {
skip: queryParameters.skip,
take: queryParameters.take,
orderby: queryParameters.orderby,
sortdirection: queryParameters.sortdirection,
filter: queryParameters.filter
}).success(function (data, status) {
deferred.resolve(data);
}).error(function (data, status) {
deferred.reject(status);
});
return deferred.promise;
}
}});
When this call occurs, the response status is 200, and in the data, the html for the login page is returned.
Moreover, I can see on Chrome's Network tab that the response has a Location header with the url of the Login page. However, if I set up an http interceptor, I only see the Accept header has been passed to the javascript.
Here are the http headers displayed in Chrome's network tab:
The response does not have the Access-Control-Allow-Origin header for some reason.
So I have the following questions:
Is there a way I could get access to the Location header of the response in the angular client code to redirect to it?
How might I be able to get the server to send me a 401 instead of 200 in order to know that there was an authentication error?
Is there a better way to do this, and if so, how?
Thanks for your help!
EDIT:
I have added a custom AuthorizeAttribute to determine what http status code is returned from the filter.
The custom filter code
public class BearerTokenAutorizeAttribute : AuthorizeAttribute
{
private const string AjaxHeaderKey = "X-Requested-With";
private const string AjaxHeaderValue = "XMLHttpRequest";
protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
{
var headers = actionContext.Request.Headers;
if(IsAjaxRequest(headers))
{
if (actionContext.RequestContext.Principal.Identity.IsAuthenticated)
actionContext.Response.StatusCode = System.Net.HttpStatusCode.Forbidden;
else
actionContext.Response.StatusCode = System.Net.HttpStatusCode.Unauthorized;
}
base.HandleUnauthorizedRequest(actionContext);
var finalStatus = actionContext.Response.StatusCode;
}
private bool IsAjaxRequest(HttpRequestHeaders requestHeaders)
{
return requestHeaders.Contains(AjaxHeaderKey) && requestHeaders.GetValues(AjaxHeaderKey).FirstOrDefault() == AjaxHeaderValue;
}
I have observed two things from this: first, the X-Requested-With header is not included in the request generated by the $http service on the client side. Moreover, the final http status returned by the base method is 401 - Unauthorized. This implies that the status code is changed somewhere up the chain.
Please don't feel like you have to respond to all the questions. Any help would be greatly appreciated!
You have probably configured the server correctly since you are getting
the login page html as a response to the angular $http call -> it is
supposed to work this way:
angularjs $http
Note that if the response is a redirect, XMLHttpRequest will transparently follow it, meaning that the outcome (success or error) will be determined by the final response status code.
You are getting a 200 OK response since that is the final response as the redirect is instantly followed and it's result resolved as the $http service outcome, also the response headers are of the final response
One way to achieve the desired result - browser redirect to login page:
Instead of redirecting the request server side (from the web project to the Identity Server) the web api controller api/pitchingstats/GetFilteredPlayer could return an error response (401) with a json payload that contains a {redirectUrl: 'login page'} field or a header that could be read as response.headers('x-redirect-url')
then navigate to the specified address using window.location.href = url
Similar logic can often be observed configured in an $httpInterceptors that handles unauthorized access responses and redirects them to the login page - the redirect is managed on the client side

webapi owin use token and cookie

I have two main projects in my Web application:
WebApi project as back-end to serve authentication and authorization for the Web project,using OWIN 2 with bearer tokens.
Web project uses Angularjs.
The Web project works as expected(authentication and authorization are working)
Method: store token to localstorage, and send it using interceptors each request.
Now I want to add authentication and authorization to the the WebApi project,which would serve other modules like Hangfire,Elmah and Help pages.
I added the same login logic, which works(Authorizing) and then redirect to Dashboard page(using Angularjs) which works.
But going to any other page(one of the mentioned modules) don't work.By not working: The user from the Owin context always null/empty.(see code)
For my understanding, I need somehow to send the token with each request which doesn't happen here.
Questions:
How can I achieve that(sending/getting the token)?
If cookie is the only/better approach ↴
How can I integrate cookie for project 1 and token for project 2?(Tried to use cookies, but it seems I'm doing it wrong, or does it work simultaneously with bearer tokens?)
Code:
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
Provider = new SimpleAuthorizationServerProvider(),
RefreshTokenProvider = new SimpleRefreshTokenProvider()
};
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
GlobalConfiguration.Configure(WebApiConfig.Register);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
AreaRegistration.RegisterAllAreas();
app.UseHangfire(hangfireConfig =>
{
config.UseAuthorizationFilters(
new AuthorizationFilter { Users = "admin, superuser", Roles = "advanced" },
new ClaimsBasedAuthorizationFilter("name", "value")
);
hangfireConfig.UseSqlServerStorage("Context");
hangfireConfig.UseServer();
});
}
I tried for testing purposes:
public class HFAuthorizationFilter : Hangfire.Dashboard.IAuthorizationFilter
{
public bool Authorize(IDictionary<string, object> owinEnvironment)
{
var context = new OwinContext(owinEnvironment);
if (context.Authentication.User == null)
return false;//Always null
return context.Authentication.User.HasClaim(ClaimTypes.Role, "SuperAdmin")
|| context.Authentication.User.HasClaim(ClaimTypes.Role, "Admin");
}
}
and in Configuration:
app.UseHangfire(hangfireConfig =>
{
hangfireConfig.UseAuthorizationFilters(
new HFAuthorizationFilter()
);
hangfireConfig.UseSqlServerStorage("Context");
hangfireConfig.UseServer();
});
Potential duplicate:
Passing and verifying the OWIN Bearer token in Query String in WebAPI
if i understood correctly, you are looking to implement token generation in one api and use the same token in other api. if that is the case then you need master api to be the token generator and child or dependent api to consume the token. Please find master and child API config for oauth
Master API config:
public void ConfigureOAuth(IAppBuilder app)
{
//configure OAuth using owin framework
var oAuthOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/api/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromHours(2),
Provider = new KatanaAuthorizationServerProvider()
};
app.UseOAuthAuthorizationServer(oAuthOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
Child API config:
public void ConfigureAuth(IAppBuilder app)
{
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}

Resources