SignalR 403 status code on websocket transport handshake - websocket

I am mapping signalR in Web Api by following code in Startup.cs class
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
EnableDetailedErrors= true,
EnableJSONP=true
};
map.RunSignalR(hubConfiguration);
});
}
Along with it i used Bearer token authentication and cookies authentication in Web Api by following code
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
AuthenticationMode = AuthenticationMode.Active,
CookieHttpOnly = true,
CookieSecure = CookieSecureOption.SameAsRequest,
CookiePath = "/",
CookieDomain = "xxxx.cloudapp.net",
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = true,
};
app.UseOAuthBearerTokens(OAuthOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
{
Provider = new QueryStringOAuthBearerProvider("Token")
});
Web Api is on different domain so i enabled Cors for Api calls by following code
public static void Register(HttpConfiguration config)
{
var cors = new EnableCorsAttribute("http://localhost:8080,http://www.myweb.com,http://myweb.com", "*", "*");
cors.SupportsCredentials = true;
config.EnableCors(cors);
......
......
}
Now, while connecting from client side, I am getting following error in console
Here is response that i am getting in corresponding to websocket handshake
Please guide on this.

I know this is an old question, but I've had the same problem, so for future reference if anyone else stumbles upon it...
Somehow this:
CookieSecure = CookieSecureOption.SameAsRequest,
is the problem.
It doesnt work as it should (don't know why)...
This is my cookie configuration:
builder.Register(ctx => new CookieAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
CookieName = "xxx",
CookieHttpOnly = false, // Kako bi mu mogli pristupiti iz Javascripta
ExpireTimeSpan = TimeSpan.FromDays(1),
LoginPath = PathString.Empty,
LogoutPath = PathString.Empty,
SlidingExpiration = true,
#if DEBUG
CookieSecure = CookieSecureOption.SameAsRequest,
#else
CookieSecure = CookieSecureOption.Always,
#endif
CookieDomain = "localhost"
});
and this is my token configuration
builder.Register(ctx => new OAuthAuthorizationServerOptions
{
AuthorizeEndpointPath = new PathString("/api/authorize"),
TokenEndpointPath = new PathString("/api/token"),
ApplicationCanDisplayErrors = true,
Provider = ctx.Resolve<ApplicationOAuthProvider>(),
//RefreshTokenProvider = ctx.Resolve<ApplicationRefreshTokenProvider>(),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
#if DEBUG
AllowInsecureHttp = true
#endif
});
After hosting my application on HTTPS localhost it automagicaly worked.
Why? Still don't know :P

Related

send custom object in response when jwt authentication fails in asp.net web api

I have created a ASP.NET WEB.API project with OWIN JWT Authentication. Is is working as expected, but what I want is to show custom validation message to use instead of default message if JWT authentication fails.
Right now it shows
{
"message": "Authorization has been denied for this request."
}
This is my Validation Code.
public class OwinStartUp
{
public void Configuration(IAppBuilder app)
{
HttpStatusCode statusCode;
HttpResponseMessage message = new HttpResponseMessage();
try
{
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "http://jwt.com",
ValidAudience = "http://jwt.com",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("jwt_key_asdf"))
}
});
}
catch (SecurityTokenValidationException e )
{
statusCode = HttpStatusCode.Unauthorized;
message = new HttpResponseMessage(HttpStatusCode.Unauthorized)
{
Content = new StringContent("Failed") /////// Even tried this but it does not work.
};
}
catch(Exception ex)
{
}
}
}

Jwt token always return 401 .net core 3.1 web api

I'm new at the Jwt. I create new web api running on 3.1 version and my configuration like that ;
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
var symmetricKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("mysupersecretkeytosharewithnooneandalwaysinsideapp"));
TokenValidationParameters tokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = "Management",
ValidateIssuer = true,
ValidAudience = "Management",
ValidateAudience = true,
ValidateLifetime = true,
IssuerSigningKey = symmetricKey,
ValidateIssuerSigningKey = true,
};
services.AddCors();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = tokenValidationParameters;
});
services.AddHttpContextAccessor();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors(q => q.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
And my token generator class like that ;
public static string GenerateToken(string jwtKey, string jwtExpireMinutes)
{
var claims = new List<Claim>()
{
new Claim(ClaimTypes.NameIdentifier,"C280298D-D896-49E2-96AD-5C82243F9048"),
new Claim(ClaimTypes.Email,"mfa#gmail.com"),
};
var keyByte = Encoding.UTF8.GetBytes(jwtKey);
var signInKey = new SymmetricSecurityKey(keyByte);
var expireMinutes = DateTime.Now.AddMinutes(Convert.ToDouble(jwtExpireMinutes));
var token = new JwtSecurityToken(claims: claims, expires: expireMinutes, signingCredentials: new SigningCredentials(signInKey, SecurityAlgorithms.HmacSha256));
return new JwtSecurityTokenHandler().WriteToken(token);
}
I tried on Postman and I'm getting token successfuly but with this token When I call my method it returns 401 unauthorized.
Controller has these attributes ;
[ApiController]
[Route("api/[controller]")]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
These are the results ;
That is because you check the aud (audience) and iss (issuer) claim in your jwt token when validating token :
ValidIssuer = "Management",
ValidateIssuer = true,
ValidAudience = "Management",
ValidateAudience = true,
So that when creating token you should adding these correct claims ,otherwise token validation won't pass :
var token = new JwtSecurityToken(audience: "Management", issuer: "Management", claims: claims, expires: expireMinutes, signingCredentials: new SigningCredentials(signInKey, SecurityAlgorithms.HmacSha256));

which TokenValidationParameters are needed with UseJwtBearerAuthentication

I am tying to do JwtBearerAuthentication on my .net WebAPI and it is just not working. The Authorize attribute is always claiming isAuthorized = false.
I am working with Okta as the SSO. I am authenticating on my client side and getting both an access token and id token. On a webapi get request I am providing the access token (i have also tried the id token) in the authorize header and I am able to see the authorize header with the token in the webapi actioncontext.
In my startup.cs I have the following
var clientID = WebConfigurationManager.AppSettings["okta:ClientId"];
var oidcIssuer = WebConfigurationManager.AppSettings["okta:OIDC_Issuer"];
TokenValidationParameters tvps = new TokenValidationParameters
{
ValidAudience = clientID,
ValidateAudience = true,
ValidIssuer = oidcIssuer,
ValidateIssuer = true
};
app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
{
TokenValidationParameters = tvps,
IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
{
new OpenIdConnectCachingSecurityTokenProvider(oidcIssuer + "/.well-known/openid-configuration")
}
});
Am i missing some TokenValidationParameters that I need?
As I was typing this, I see that twaldron was able to figure it out!
I also realized that he was asking about WebAPI, and not MVC. However, here is the code that I needed to get the following working with ASP.NET Core MVC, of particular interest might be this line, which is necessary to get access to the additional claims in the JWT:
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
Here is how this code sample works from the command line, the $ID_TOKEN variable contains a valid JWT:
$ curl -H "Authorization: Bearer ${ID_TOKEN}" http://localhost:3000/test/test
sub: 01a23b4cd5eFgHI6j7k8 email:test#example.com
Setup.cs:
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
namespace WebApplication
{
public class Startup
{
readonly string clientId = string.Empty;
readonly string issuer = string.Empty;
readonly string audience = string.Empty;
public Startup(IHostingEnvironment env)
{
clientId = "A0b1CDef2GHIj3k4lm5n";
issuer = "https://example.okta.com";
audience = "A0b1CDef2GHIj3k4lm5n";
}
public IConfigurationRoot Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddDebug();
// https://github.com/aspnet/Security/issues/1043#issuecomment-261937401
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
TokenValidationParameters tvps = new TokenValidationParameters
{
ValidateAudience = true,
ValidAudience = audience,
ValidateIssuer = true,
ValidIssuer = issuer,
ValidateLifetime = true,
ClockSkew = TimeSpan.FromMinutes(5)
};
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
MetadataAddress = issuer + "/.well-known/openid-configuration",
TokenValidationParameters = tvps
});
app.UseStaticFiles();
// Add external authentication middleware below. To configure them please see https://go.microsoft.com/fwlink/?LinkID=532715
app.UseMvc(routes =>
{
routes.MapRoute(
name: "test-controller",
template: "test/{action}",
defaults: new { controller = "Test", action = "Index" }
);
routes.MapRoute(
name: "default",
template: "{controller=Test}/{action=Index}/{id?}");
});
}
}
}
In Controllers/Test.cs:
[Authorize]
public IActionResult Test()
{
var contextUser = User.Identity as ClaimsIdentity;
Dictionary<string, string> claim = contextUser.Claims.ToDictionary(x => x.Type, x => x.Value);
var output = "sub: " + claim["sub"] + " email:" + claim["email"];
return Content(output);
}
My problem was not with the options.
It was 100% the need to move
app.UseWebApi(config);
below all the owin setup stuff.

Can we use OAuth to authenticate the consumers in my Web API?

I am developing a web application, mobile application and desktop application which all can access the data with the help of a single API which can be developed by ASP.NET Web API.
In my Web API can I authenticate the user credentials and the consumer Application key with the help of OAuth?
Can you guys guide me to achieve the same with any examples?
Add the following lines in startup class
public class Startup
{
public void Configuration(IAppBuilder app)
{
var oauthProvider = new OAuthAuthorizationServerProvider
{
OnGrantResourceOwnerCredentials = async context =>
{
IsValid = true;
//You can get the username and password by context.username and context.password
if (IsValid)
{
var claimsIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
claimsIdentity.AddClaim(new Claim("user", context.UserName));
context.Validated(claimsIdentity);
return;
}
context.Rejected();
},
OnValidateClientAuthentication = async context =>
{
string clientId;
string clientSecret;
if (context.TryGetBasicCredentials(out clientId, out clientSecret))
{
if (clientId == GlobalAppSettings.SystemSettings.ApplicationKey)
{
context.Validated();
}
}
}
};
var oauthOptions = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/accesstoken"),
Provider = oauthProvider,
AuthorizationCodeExpireTimeSpan = TimeSpan.FromMinutes(1),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(3),
SystemClock = new SystemClock()
};
app.UseOAuthAuthorizationServer(oauthOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
app.UseWebApi(config);
}
}
And invoke the startup method by start up the new OAuth APP from where you need the authorization and OAuth token
You can use your own host by using the self hosting namespace.
Otherwise you can use Microsoft.Owin.Host.HttpListener namespace and host the OAuth app in different host as below
var Basesite = "http://localhost:9327/";
var homeProcessorModel = new HomeProcessorModel();
using (WebApp.Start<Startup>(url: Basesite))
{
var client = new HttpClient();
var form = new Dictionary<string, string>
{
{"grant_type","password"},
{"userName",username},
{"passWord",password}
};//If you are using grant_type as password, you have to send the username and password to OAuth protocol.
var tokenResponse = client.PostAsync(Basesite + "accesstoken", new FormUrlEncodedContent(form)).Result;
var token = tokenResponse.Content.ReadAsAsync<Token>(new[] { new JsonMediaTypeFormatter() }).Result;
//You can get the token with token.AccessToken object
}

Enrich ASP.Net bearer token format

I have setup an ASP.NET WebApi project with support of bearer token like this:
var oAuthServerOptions = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider()
};
var oAuthBearerOptions = new OAuthBearerAuthenticationOptions();
app.UseOAuthAuthorizationServer(oAuthServerOptions);
app.UseOAuthBearerAuthentication(oAuthBearerOptions);
When I make a request to the token endpoint I have this answer
{
"access_token":"GST9UwSuesiYhkezr94K4xwuzvNQ",
"token_type":"bearer",
"expires_in":86399
}
Is there any way to enrich the token with additional fields like this?
{
"access_token":"GST9UwSuesiYhkezr94K4xwuzvNQ",
"token_type":"bearer",
"expires_in":86399,
"username":"user#mail.com"
}
Well here is the solution:
In your class that inherits from OAuthAuthorizationServerProvider
public override async Task TokenEndpoint(OAuthTokenEndpointContext context)
{
context.AdditionalResponseParameters.Add("username", "user#mail.com");
return Task.FromResult<object>(null);
}

Resources