CORS error on requesting OWIN token - asp.net-web-api

I need to implement OWIN authorization from web api server. Below is my startup class.
[assembly: OwinStartup(typeof(SpaServerSide.MyStartUp))]
namespace SpaServerSide
{
public class MyStartUp
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
app.Map("/signalr", map =>
{
map.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
var hubConfig = new Microsoft.AspNet.SignalR.HubConfiguration { };
map.RunSignalR(hubConfig);
});
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/#")
});
OAuthAuthorizationServerOptions OAuthOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/Token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(5),
Provider = new SpaServerSide.Shared.OAuthTokenServer()
};
app.UseOAuthAuthorizationServer(OAuthOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
}
}
Then, I implement the OAuthAuthorizationServerProvider as the following :
public class OAuthTokenServer : OAuthAuthorizationServerProvider
{
public ASPIdentityUserManager cusUserManager;
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
var user = await cusUserManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "Username and password do not match.");
return;
}
var identity = await cusUserManager.CreateIdentityAsync(user, context.Options.AuthenticationType);
context.Validated(identity);
}
}
After that, I have hosted the web server on http://localhost:5587 and client web site on http://localhost. When I tried to request the token using Angular JS, the browser threw me an CORS error. The message is as follows :
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at http://localhost:5587/Token. (Reason: CORS
header 'Access-Control-Allow-Origin' missing).
Please suggest me anything I would have missed.

Move the line:
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
at the beginning of your Configuration() method.
You have to configure CORS middleware before oauth middleware. And before signalr middleware if you need it.

Try this
Enable browser setting for allowing cross origin access
IE: http://www.webdavsystem.com/ajax/programming/cross_origin_requests
Firefox: How to enable CORS on Firefox?
Chrome: https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en

I think u need enable CORS in your server side. U can refer to this http://enable-cors.org/server.html . Click link based on your server.
Hope that help u. :)

Related

What am I missing? ASP.NET Core 6 keycloak integration, authentication fails after successful login

Here is what I did: using my local keycloak server (thru docker), I created a realm, users, role and client with this setup :
I set up credentials and got secret key and stuff and that's it, I haven't set anything, no mappers, client scope, etc.
I did this as our other applications that is using other languages such as PHP or nodejs have similar settings.
services.AddAuthentication(options =>
{
//Sets cookie authentication scheme
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(cookie =>
{
//Sets the cookie name and maxage, so the cookie is invalidated.
cookie.Cookie.Name = "keycloak.cookie";
cookie.Cookie.MaxAge = TimeSpan.FromMinutes(60);
cookie.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
cookie.SlidingExpiration = true;
})
.AddOpenIdConnect(options =>
{
//Use default signin scheme
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
//Keycloak server
options.Authority = Configuration.GetSection("Keycloak")["ServerRealm"];
//Keycloak client ID
options.ClientId = Configuration.GetSection("Keycloak")["ClientId"];
//Keycloak client secret
options.ClientSecret = Configuration.GetSection("Keycloak")["ClientSecret"];
//Keycloak .wellknown config origin to fetch config
// options.MetadataAddress = Configuration.GetSection("Keycloak")["Metadata"];
//Require keycloak to use SSL
options.RequireHttpsMetadata = false;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
//Save the token
options.SaveTokens = true;
//Token response type, will sometimes need to be changed to IdToken, depending on config.
options.ResponseType = OpenIdConnectResponseType.Code;
//SameSite is needed for Chrome/Firefox, as they will give http error 500 back, if not set to unspecified.
options.NonceCookie.SameSite = SameSiteMode.None;
options.CorrelationCookie.SameSite = SameSiteMode.None;
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "https://schemas.scopic.com/roles"
};
Configuration.Bind("<Json Config Filter>", options);
options.Events.OnRedirectToIdentityProvider = async context =>
{
context.ProtocolMessage.RedirectUri = "http://localhost:13636/home";
await Task.FromResult(0);
};
});
Then I created a fresh ASP.NET Core MVC application and setup the OpenId options like so
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
My HomeController looks like this:
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
bool value = User.Identity.IsAuthenticated;
return View();
}
[Authorize]
public IActionResult Privacy()
{
return View();
}
}
When I access localhost:13636/Privacy to test, the Keycloak login page is triggered which is correct, but after successful login and a redirect to /home, User.Identity.IsAuthenticated is false and it seems like the application doesn't know that authentication has been successful.
What needs to be done after this?
Or am I missing some configuration/settings/options?
Summary of what I did
Setup keycloak dashboard (created Realm, client, user and roles)
Setup a simple ASP.NET Core MVC application, pass openid options and controller.
The keycloak login page is triggered but authentication fail during test
Try to add to the AddCookie handler the following setting:
options.Cookie.SameSite = SameSiteMode.None;
To make sure the cookies are set with SameSite=none.

Is possible to protect scope (web api) and authenticate client (web app mvc) in same project?

Good morning,
I need to have in same project both web api and web app mvc.
Web api has to be protected via bearer token and web app mvc has to be authenticated via identity server.
Is it possible protecting a scope and a client in same project?
I think I have to do something like this in startup
//this to protect scope api1
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "http://localhost:5000/";
options.RequireHttpsMetadata = false;
options.Audience = "api1";
});
//this to authenticate mvc client
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies", options =>
{
options.AccessDeniedPath = "/account/denied";
})
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.Authority = "http://localhost:5000",
options.RequireHttpsMetadata = false;
options.ResponseType = "id_token token";
options.ClientId = "mvc-implicit";
options.SaveTokens = true;
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("api1");
options.GetClaimsFromUserInfoEndpoint = true;
options.ClaimActions.MapJsonKey("role", "role", "role");
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
});
Now, I have to call my Api1 using client_credential with an external client.
But it returns me at login page.
Is it possible to do what I want?
Protected WebApi and Authenticated MVC client in same project?
Now, I have to call my Api1 using client_credential with an external client. But it returns me at login page.
That seems you misunderstand the scenario . Your MVC application is client also is a resource application which protected by Identity Server (in Config.cs):
public static IEnumerable<ApiResource> GetApis()
{
return new List<ApiResource>
{
new ApiResource("api1", "My API")
};
}
I assume you have api controller in your MVC application :
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET: api/Values
[HttpGet]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
And you have config to protect the api actions by using AddJwtBearer :
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "http://localhost:5000/";
options.RequireHttpsMetadata = false;
options.Audience = "api1";
});
That means any request to access the Get action should have an authentication bearer header with access token append , the access token is issued by your Identity Server(endpoint is http://localhost:5000/) and the audience is api1 .
Now your another client could use client credential flow to acquire access token to access your web application :
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5000");
if (disco.IsError)
{
Console.WriteLine(disco.Error);
return;
}
// request token
var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "client",
ClientSecret = "secret",
Scope = "api1"
});
And call your protected actions :
var apiClient = new HttpClient();
apiClient.SetBearerToken(tokenResponse.AccessToken);
var response = await apiClient.GetAsync("http://localhost:64146/api/values");
if (!response.IsSuccessStatusCode)
{
Console.WriteLine(response.StatusCode);
}
else
{
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(JArray.Parse(content));
}
So it won't redirect to login page , since client credential in fact is sending HTTP POST request to get access token with app's credential . There is no login page in this scenario .

Web app and web api authentication in same application

I have a web app MVC,using auth0 owin regular web app cookie based authentication.
This web app also has webapis which is used internally in the application. However i have a requirement to call this webapis from outside the application. So i created a restclient and tried to implement jwtbearerauthentication in application (but cookie based on authentication still in place).
Now when i call the webapi from other application it validates the bearer token gives no error however it redirects to login page due to cookie based authentication.
startup file:
public partial class Startup
{
private IPlatform platform;
public void ConfigureAuth(IAppBuilder app, IPlatform p, IContainer container)
{
platform = p;
// 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"),
ExpireTimeSpan = System.TimeSpan.FromDays(2),
SlidingExpiration = true
});
// Use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
var provider = new Auth0.Owin.Auth0AuthenticationProvider
{
OnReturnEndpoint = (context) =>
{
// xsrf validation
if (context.Request.Query["state"] != null && context.Request.Query["state"].Contains("xsrf="))
{
var state = HttpUtility.ParseQueryString(context.Request.Query["state"]);
AntiForgery.Validate(context.Request.Cookies["__RequestVerificationToken"], state["xsrf"]);
}
return System.Threading.Tasks.Task.FromResult(0);
},
OnAuthenticated = (context) =>
{
var identity = context.Identity;
//Add claims
var authenticationManager = container.Resolve<IAuthenticationManager>();
authenticationManager.AddClaims(identity);
if (context.Request.Query["state"] != null)
{
authenticationManager.AddReturnUrlInClaims(identity, context.Request.Query["state"]);
}
return System.Threading.Tasks.Task.FromResult(0);
}
};
var issuer = "https://" + ConfigurationManager.AppSettings["auth0:Domain"] + "/";
var audience = ConfigurationManager.AppSettings["auth0:ClientId"];
var secret = TextEncodings.Base64.Encode(TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["auth0:ClientSecret"]));
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
AllowedAudiences = new[] { audience },
IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
{
new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret)
}
});
app.UseAuth0Authentication(
clientId: platform.ServerRole.GetConfigurationSettingValue("auth0:ClientId"),
clientSecret: platform.ServerRole.GetConfigurationSettingValue("auth0:ClientSecret"),
domain: platform.ServerRole.GetConfigurationSettingValue("auth0:Domain"),
provider: provider);
}
}
webapiconfig file:
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new {id = RouteParameter.Optional});
config.Filters.Add(new AuthorizeAttribute());
ODataConfig.Setup(config);
var clientID = WebConfigurationManager.AppSettings["auth0:ClientId"];
var clientSecret = WebConfigurationManager.AppSettings["auth0:ClientSecret"];
config.MessageHandlers.Add(new JsonWebTokenValidationHandler()
{
Audience = clientID,
SymmetricKey = clientSecret
});
}
Currently creating the jwt token from below code and posting using postman in header just to check if it works.. but redirects to login page.
string token = JWT.Encode(payload, secretKey, JwsAlgorithm.HS256);
I suspect what's happening is that your call to the API has a bearer token which fails validation (or there is no Authorize token at all), your API controller has an Authorize attribute, which, since there is no valid ClaimsPrincipal on the call throws 401. Auth0AuthenticationProvider picks that and assumes the call was to UI so redirects for user authentication. You may want to add an override in the Oauth0Provider to trap OnRedirectToIdP (or something like that), inspect the request and if it is to API, abot further handling and return Unauthorized.
Remove any [Authorize] from your API and see whether it works then. Also make sure your startup does not require Authorize for all controllers.
You may want to remove the authn part of your code (cookie and Oauth2Provider) and see whether you are getting to the API then.
A few years late i know, but i recently came across the same requirement in a project, and found this sample put together by a dev at Auth0.
https://github.com/auth0-samples/aspnet-core-mvc-plus-webapi
The example in the link allows for cookie authentication OR token authentication for the API endpoints.
The key takeaway for me was using attributes on your routes to tell the pipline what authentication mechanism to use. In my case i wanted cookie authentication for the UI and token authentication for the endpoints. i had no requirement to use both for any single area of the project.
controller:
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[HttpGet]
[Route("api")]
public string TestAuth()
{
return "All good " + this.User.FindFirst(ClaimTypes.NameIdentifier).Value + ". You only get this message if you are authenticated.";
}

Enable CORS for Web Api 2 and OWIN token authentication

I have an ASP.NET MVC 5 webproject (localhost:81) that calls functions from my WebApi 2 project (localhost:82) using Knockoutjs, to make the communication between the two projects I enable CORS. Everything works so far until I tried to implement OWIN token authentication to the WebApi.
To use the /token endpoint on the WebApi, I also need to enable CORS on the endpoint but after hours of trying and searching for solutions it is still now working and the api/token still results in:
XMLHttpRequest cannot load http://localhost:82/token. No 'Access-Control-Allow-Origin' header is present on the requested resource.
public void Configuration(IAppBuilder app)
{
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
TokenConfig.ConfigureOAuth(app);
...
}
TokenConfig
public static void ConfigureOAuth(IAppBuilder app)
{
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<AppUserManager>(AppUserManager.Create);
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider()
};
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
AuthorizationProvider
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
var appUserManager = context.OwinContext.GetUserManager<AppUserManager>();
IdentityUser user = await appUserManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
... claims
}
IdentityConfig
public static AppUserManager Create(IdentityFactoryOptions<AppUserManager> options, IOwinContext context)
{
// Tried to enable it again without success.
//context.Response.Headers.Add("Access-Control-Allow-Origin", new[] {"*"});
var manager = new AppUserManager(new UserStore<AppUser>(context.Get<ApplicationDbContect>()));
...
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider =
new DataProtectorTokenProvider<AppUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
EDIT:
1. Important note is that opening the endpoint directly (localhost:82/token) works.
2. Calling the Api (localhost:82/api/..) from the webproject also works, so the CORS is enabled for WebApi.
I know your issue was solved inside comments, but I believe is important to understand what was causing it and how to resolve this entire class of problems.
Looking at your code I can see you are setting the Access-Control-Allow-Origin header more than once for the Token endpoint:
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
And inside GrantResourceOwnerCredentials method:
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
This, looking at the CORS specifications, is itself an issue because:
If the response includes zero or more than one Access-Control-Allow-Origin header values, return fail and terminate this algorithm.
In your scenario, the framework is setting this header two times, and understanding how CORS must be implemented, this will result in the header removed in certain circumstances (possibly client-related).
This is also confirmed by the following question answer: Duplicate Access-Control-Allow-Origin: * causing COR error?
For this reason moving the call to app.UseCors after the call to ConfigureOAuth allows your CORS header to be set only once (because the owin pipeline is interrupted at the OAuth middleware, and never reaches the Microsoft CORS middleware for the Token endpoint) and makes your Ajax call working.
For a better and global solution you may try to put again app.UseCors before the OAuth middleware call, and remove the second Access-Control-Allow-Origin insertion inside GrantResourceOwnerCredentials.
Follow below steps and you will have your API working:
Remove any code like config.EnableCors(), [EnableCors(header:"*"....)] from your API.
Go to startup.cs and add below line
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
before
ConfigureAuth(app);
Uou will also need to install Microsoft.owin.cors package to use this functionality
Solving the problem without using app.UseCors()
I had the same problem. I used a Vue.Js client with axois to access my REST-API with cross-corps. On my Owin-Api-Server I was not able to add Microsoft.Owin.Cors nuget due to version conflicts with other 3rd party components. So I couldn't use app.UseCors() method but I solved it by using the middleware pipeline.
private IDisposable _webServer = null;
public void Start(ClientCredentials credentials)
{
...
_webServer = WebApp.Start(BaseAddress, (x) => Configuration(x));
...
}
public void Configuration(IAppBuilder app)
{
...
// added middleware insted of app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.Use<MyOwinMiddleware>();
app.UseWebApi(config);
...
}
public class MyOwinMiddleware : OwinMiddleware
{
public MyOwinMiddleware(OwinMiddleware next) :
base(next)
{ }
public override async Task Invoke(IOwinContext context)
{
var request = context.Request;
var response = context.Response;
response.OnSendingHeaders(state =>
{
var resp = (IOwinResponse)state;
// without this headers -> client apps will be blocked to consume data from this api
if (!resp.Headers.ContainsKey("Access-Control-Allow-Origin"))
resp.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
if (!resp.Headers.ContainsKey("Access-Control-Allow-Headers"))
resp.Headers.Add("Access-Control-Allow-Headers", new[] { "*" });
if (!resp.Headers.ContainsKey("Access-Control-Allow-Methods"))
resp.Headers.Add("Access-Control-Allow-Methods", new[] { "*" });
// by default owin is blocking options not from same origin with MethodNotAllowed
if (resp.StatusCode == (int)HttpStatusCode.MethodNotAllowed &&
HttpMethod.Options == new HttpMethod(request.Method))
{
resp.StatusCode = (int)HttpStatusCode.OK;
resp.ReasonPhrase = HttpStatusCode.OK.ToString();
}
}, response);
await Next.Invoke(context);
}
}
So I created my own middleware and manipulated the response. GET calls only needed the Access-Control-Allow headers whereas for OPTIONS calls I also needed to manipulate the StatusCode because axois.post() is calling first with OPTIONS-method before sending the POST. If OPTIONS return StatusCode 405, the POST will never be sent.
This solved my problem. Maybe this can help somebody too.

ASP.NET WEB API 2 OWIN Authentication unsuported grant_Type

Hi I am trying to set up OAuth bearrer token authentication in my ASP.NET Web API 2 project.
I have two project one will be the WEB API Project and the other a SPA project.
Here is what I have done so far:
I have created the OWIN Startup class:
[assembly: OwinStartup(typeof(CodeArt.WebApi.App_Start.Startup))]
namespace CodeArt.WebApi.App_Start
{
public class Startup
{
static Startup()
{
PublicClientId = "self";
UserManagerFactory = () => new UserManager<UserModel>(new UserStore<UserModel>());
OAuthOptions = new OAuthAuthorizationServerOptions {
TokenEndpointPath = new PathString("/Token"),
Provider = new OAuthAuthorizatonServer(PublicClientId, UserManagerFactory),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = true
};
}
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
public static Func<UserManager<UserModel>> UserManagerFactory { get; set; }
public static string PublicClientId { get; private set; }
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalBearer);
app.UseOAuthBearerTokens(OAuthOptions);
}
}
I have configured Web API to use only bearer token authentication:
private static void ConfigureBearerTokenAuthentication(HttpConfiguration config)
{
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(Startup.OAuthOptions.AuthenticationType));
}
I have configured WEB API to support CORS:
private static void ConfigureCrossOriginResourseSharing(HttpConfiguration config)
{
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
}
I have created the OAuthAuthorizationServerProvider class.From this class I only managed to make my code call this method:
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
if(context.ClientId == null)
{
context.Validated();
}
return Task.FromResult<object>(null);
}
The if condition inside of it always gets executed.
On my spa project I have the following:
This is my viewModel:
var vm = {
grant_type: "password",
userName: ko.observable(),
password: ko.observable()
};
When the login button gets clicked I call this function:
var http = {
post:function(url, data) {
return $.ajax({
url: url,
data: data,
type: 'POST',
contentType: 'application/json',
dataType: 'jsonp'
});
}
}
function loginClick() {
var model = ko.mapping.toJS(vm.loginModel);
var rez = $.param(model);
http.post("http://localhost:3439/Token", rez)
.done(function (data) {
console.log(data);
})
.fail(function(eror, stuff, otherstuff) {
console.log(eror);
console.log(stuff);
console.log(otherstuff);
});
}
My first attempt I have set the post calls dataType to json and I got this errors:
OPTIONS ...:3439/Token 400 (Bad Request) jquery.js:7845
OPTIONS ...:3439/Token No 'Access-Control-Allow-Origin'
header is present on the requested resource. Origin
'...:3304' is therefore not allowed access.
jquery.js:7845
XMLHttpRequest cannot load ...3439/Token. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin '...3304' is therefore not allowed
access.
The 3 dots represent http://localhost.
The second time arround I set it datatype to jsonp and I got back an error that stated unsupported "unsupported_grant_type".
Both calls make it to ValidateClientAuthentication that I mentioned above but they are both sent back as a failed request.
Now I am guessing that the problem is more related to how I am sending data instead of the grand_type because the SPA template in Visual Studion set's the grant type to grant_type: "password" like I did.
Also I have read that I have to serialize the data not send it in json in order for this to work here is the exact json serialized data that get's sent:
"grant_type=password&userName=aleczandru&password=happynewYear&moduleId=models%2FappPostModels%2FloginModel"
The model id property get's set to all my object in my SPA template by Durandal Framework.
Can anyone tell me what I am doing wrong I have been trying to figure this out for the last two days?
Add the following line of code to GrantResourceOwnerCredentials, which will add the header to the response.
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
for more information refer to:
web-api-2-0-cors-and-individual-account-identity
Like Robin Karlsson said, you should use:
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
in your Startup configuration.
And make sure it's the only cors statement (don't mix them) and the first statement in your Startup.

Resources