401 Unauthorized beim senden von ajax-request web-api
Ich habe meinen Kopf kratzen auf diese für 2 Tage jetzt. Ich bin mit WebAPI version 2.2 und ich bin mit CORS. Dieses setup funktioniert auf der server-Seite, darf ich mich zu bekommen, autorisierte Inhalte von meiner web-client-server-code, aber immer nicht in meine ajax-calls.
Hier ist meine Konfiguration:
Web-API-Config
WebApiConfig:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//Web API configuration and services
//Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
config.Filters.Add(new HostAuthenticationFilter(DefaultAuthenticationTypes.ApplicationCookie));
//enable cors
config.EnableCors();
//Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Filters.Add(new ValidationActionFilter());
}
}
Start.Auth.cs:
//Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext(UserContext<ApplicationUser>.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
//Enable the application to use a cookie to store information for the signed in user
//and to use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
CookieHttpOnly = true,
CookieName = "Outpour.Api.Auth"
}
);
//app.UseCors(CorsOptions.AllowAll);
//app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
//Configure the application for OAuth based flow
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
};
//Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
(Ich habe versucht, jede Kombination von app.UseCors(CorsOptions.AllowAll) und config.EnableCors())
Mein Controller-Attribut:
[Authorize]
[EnableCors("http://localhost:8080", "*", "*", SupportsCredentials = true)]
[RoutePrefix("api/videos")]
public class VideosController : ApiController...
Web-Client
Ajax-Aufruf:
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
options.crossDomain = {
crossDomain: true
};
options.xhrFields = {
withCredentials: true
};
});
function ajaxGetVideoResolutionList() {
var request = {
type: "GET",
dataType: "json",
timeout: Outpour.ajaxTimeOut,
url: Outpour.apiRoot + "/videos/resolutions"
};
$.ajax(request).done(onAjaxSuccess).fail(onAjaxError);
Cookie-Erstellung:
var result = await WebApiService.Instance.AuthenticateAsync<SignInResult>(model.Email, model.Password);
FormsAuthentication.SetAuthCookie(result.AccessToken, model.RememberMe);
var claims = new[]
{
new Claim(ClaimTypes.Name, result.UserName), //Name is the default name claim type, and UserName is the one known also in Web API.
new Claim(ClaimTypes.NameIdentifier, result.UserName) //If you want to use User.Identity.GetUserId in Web API, you need a NameIdentifier claim.
};
var authTicket = new AuthenticationTicket(new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie), new AuthenticationProperties
{
ExpiresUtc = result.Expires,
IsPersistent = model.RememberMe,
IssuedUtc = result.Issued,
RedirectUri = redirectUrl
});
byte[] userData = DataSerializers.Ticket.Serialize(authTicket);
byte[] protectedData = MachineKey.Protect(userData, new[] { "Microsoft.Owin.Security.Cookies.CookieAuthenticationMiddleware", DefaultAuthenticationTypes.ApplicationCookie, "v1" });
string protectedText = TextEncodings.Base64Url.Encode(protectedData);
Response.Cookies.Add(new HttpCookie("Outpour.Api.Auth")
{
HttpOnly = true,
Expires = result.Expires.UtcDateTime,
Value = protectedText
});
Und nicht zuletzt, meine Header.
Remote Address:127.0.0.1:8888
Request URL:http://127.0.0.1/api/videos/resolutions
Request Method:GET
Status Code:401 Unauthorized
**Request Headersview source**
Accept:application/json, text/javascript, */*; q=0.01
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache
Host:127.0.0.1
Origin:http://localhost:8080
Pragma:no-cache
Proxy-Connection:keep-alive
Referer:http://localhost:8080/video/upload
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
**Response Headersview source**
Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin:http://localhost:8080
Cache-Control:no-cache
Content-Length:61
Content-Type:application/json; charset=utf-8
Date:Wed, 08 Oct 2014 04:01:19 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/8.0
WWW-Authenticate:Bearer
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
Entwickler-tools und fiddler behaupten, es wurden keine cookies gesendet, mit der Anfrage.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich glaube, Sie werden eine Vermischung von cookies, Authentifizierung und bearer-Token sind Sie hier nicht senden ein access-token in der Authorization-header mit Ihrer Anfrage, das ist, warum Sie immer 401.
So müssen Sie nur zulassen CORS mit
application.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
und entfernen Sie Sie sonst wohin aus Ihrer Controller-Attribut auch von der Konfiguration.Check my Repo hier wo habe ich umgesetzt CORS und das vordere Ende AngularJS zu. ist es korrekt funktioniert. Hier ist die live-demo auch für diese repo, offene Entwickler-tools und überwachen die Anforderungen, die Sie sehen sollten, pre-flight-Anfrage, bevor man Sie sieht Ihre HTTP-get-Anfrage.
Wenn Sie brauchen nur zu schützen Sie Ihre API mithilfe von bearer tokens dann empfehle ich dir zu Lesen Token-Basierte Authentifizierung post
Könnte dies sein, weil Sie Ihre API ist nicht auf die kam-URL als Ihre Berufung Anwendung. Ihre URL für die API ist:
http://127.0.0.1/
(ignorieren Sie den Ordner-Pfad - das spielt keine Rolle)..aber Sie fordern es von
http://127.0.0.1:8888
was zählt als eine separate Website der port ist anders. Da der browser denkt, die Seite ist anders, es wird nicht das cookie senden.Haben Sie versucht, die Tests von einer Seite, die gehostet werden auf die gleiche URL wie die API (mit dem gleichen port)?
Ganz wichtig: Überprüfen, dass Sie sehen können, die das Cookie gesendet durch in Fiddler.
Vielleicht finden Sie auch weitere Informationen über das abrufen dieses arbeiten auf diese Antwort