私は、IdentityServer3が組み込まれたAsp.NET MVC/WebAPIプロジェクトを持っています。JavascriptとWeb APIを接続してIdentityServer3で保護する
MVCとWebAPIの両方をIdentityServerで保護します。ですから、MVCコントローラとAPIコントローラの両方でAuthorize属性を使用しました。
私のテストページ(保護されている)にサーフィンすると、私はIdentityServerログインページにリダイレクトされます。私は自分のユーザー名とパスワードを入力し、認証されてリダイレクトされます。 ページ上に、私の保護されたAPIに、承認ヘッダ内のアクセストークンを使って、JavaScriptからGETをトリガーするボタンがあります。しかしここでは401 Unauthorizedで失敗します。 Razorでページにレンダリングすることで、javascriptへのアクセストークンを取得しました。
私は、IdentityServerに1クライアントがあり、ハイブリッドフローに設定されています。 MVCはクッキーを使用し、APIはベアラトークンを使用します。 API HttpConfigurationでSuppressDefaultHostAuthenticationを設定しました。私はその行を削除する場合はすべてが動作しますが、私はしたくないAPIのためのクッキーを使用します。
証明書の問題の可能性を避けるため、現在はHTTPとRequireSsl = falseのみを使用しています。
私はこれを動作させるために数日間試しましたが、私はどこにもいません。 私はこれをデバッグして401の原因になることさえ知りません。
これまでのところ、私はヘルプを検索するときにGoogleが提案するすべてのページを認識しています。
これはどのようなものか、どのようにこれをデバッグするのですか?
は、ここに私のStartup.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Trace()
.CreateLogger();
// MVC client
string authBaseAddress = "http://localhost:50319/identity";
string tokenEndpoint = authBaseAddress + "/connect/token";
string userInfoEndpoint = authBaseAddress + "/connect/userinfo";
string redirectUri = "http://localhost:50319/";
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies"
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = "hybrid_clients",
Authority = authBaseAddress,
RedirectUri = redirectUri,
ResponseType = "code id_token token",
Scope = "openid profile roles sampleApi offline_access",
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
},
SignInAsAuthenticationType = "Cookies",
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = async n =>
{
// use the code to get the access and refresh token
var tokenClient = new TokenClient(
tokenEndpoint,
"hybrid_clients",
"secret");
var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, n.RedirectUri);
if (tokenResponse.IsError)
{
throw new Exception(tokenResponse.Error);
}
// use the access token to retrieve claims from userinfo
var userInfoClient = new UserInfoClient(
new Uri(userInfoEndpoint),
tokenResponse.AccessToken);
var userInfoResponse = await userInfoClient.GetAsync();
// create new identity
var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
id.AddClaims(userInfoResponse.GetClaimsIdentity().Claims);
id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value));
n.AuthenticationTicket = new AuthenticationTicket(
new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, "name", "role"),
n.AuthenticationTicket.Properties);
},
// Attach the id_token for the logout roundtrip to IdentityServer
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
{
var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");
if (idTokenHint != null)
{
n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
}
}
return Task.FromResult(0);
}
}
});
AntiForgeryConfig.UniqueClaimTypeIdentifier = Constants.ClaimTypes.Subject;
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
// web api
app.Map("/api", a =>
{
var config = new HttpConfiguration();
a.UseCors(CorsOptions.AllowAll);
a.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
//AuthenticationMode = AuthenticationMode.Active,
Authority = authBaseAddress,
RequiredScopes = new[] { "sampleApi" },
DelayLoadMetadata = true
});
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
config.MapHttpAttributeRoutes();
a.UseWebApi(config);
});
// Identity server
app.Map("/identity", idsrvApp =>
{
idsrvApp.UseCors(CorsOptions.AllowAll);
idsrvApp.UseIdentityServer(new IdentityServerOptions
{
SiteName = "Embedded IdentityServer",
SigningCertificate = LoadCertificate(),
Factory = new IdentityServerServiceFactory()
.UseInMemoryUsers(Users.Get())
.UseInMemoryClients(Clients.Get())
.UseInMemoryScopes(Scopes.Get()),
AuthenticationOptions = new IdentityServer3.Core.Configuration.AuthenticationOptions()
{
EnablePostSignOutAutoRedirect = true // Automatically redirects back to the client on signout
},
RequireSsl = false,
});
});
}
X509Certificate2 LoadCertificate()
{
return new X509Certificate2(
string.Format(@"{0}\bin\idsrv3test.pfx", AppDomain.CurrentDomain.BaseDirectory), "idsrv3test");
}
}
私のクライアント
new Client
{
Enabled = true,
ClientName = "Hybrid Clients",
ClientId = "hybrid_clients",
Flow = Flows.Hybrid,
//AllowAccessTokensViaBrowser = false,
RedirectUris = new List<string>
{
"http://localhost:50319/"
},
PostLogoutRedirectUris = new List<string>
{
"http://localhost:50319/"
},
AllowedScopes = new List<string>
{
"openid",
"profile",
"email",
"roles",
"address",
"all_claims",
"sampleApi",
"offline_access"
},
ClientSecrets = new List<Secret>
{
new Secret("secret".Sha256())
},
AccessTokenType = AccessTokenType.Reference,
LogoutSessionRequired = true
},
マイスコープ
public static class Scopes
{
public static IEnumerable<Scope> Get()
{
var scopes = new List<Scope>
{
StandardScopes.OpenId,
StandardScopes.Profile,
StandardScopes.Email,
StandardScopes.Address,
StandardScopes.OfflineAccess,
StandardScopes.RolesAlwaysInclude,
StandardScopes.AllClaims,
new Scope
{
Enabled = true,
Name = "roles",
Type = ScopeType.Identity,
Claims = new List<ScopeClaim>
{
new ScopeClaim("role")
}
},
new Scope
{
Enabled = true,
DisplayName = "Sample API",
Name = "sampleApi",
Description = "Access to a sample API",
Type = ScopeType.Resource
}
};
return scopes;
}
}
マイAPI
[Authorize]
public class SecuredApiController : ApiController
{
public IHttpActionResult Get()
{
var user = User as ClaimsPrincipal;
var claims = from c in user.Claims
select new
{
type = c.Type,
value = c.Value
};
return Json(claims);
}
}
ですAPI用の刀ログ
function ClientAppViewModel(accessToken) {
var self = this;
self.accessToken = accessToken;
self.apiResult = ko.observable('empty');
self.callApi = function() {
console.log('CallApi');
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://localhost:50319/api/SecuredApi");
xhr.onload = function() {
self.apiResult(JSON.stringify(JSON.parse(xhr.response), null, 2));
};
xhr.setRequestHeader("Authorization", "Bearer " + self.accessToken);
xhr.send();
}
}
(Katana Documentationを参照してください)APIは401
を返して、なぜあなたはMicrosoft.Owinログのソースを使用して、これらにアクセスすることができます表示されます私は401を取得するとき。私は別の問題を調査したときに私はそこに他の情報を得たので、私はログの仕事を知っている。 – Decept
次に、あなたのAPIに401が出現しているコードを質問に入れる必要があるかもしれないと思います。私は、IdentityServerベアラトークンミドルウェアを使用していて、ログをカタログに出力していると仮定します。 –
時間を割いていただきありがとうございます。私は私の質問にすべてのコードを追加しました。はい、私はIdentityServerベアラトークンミドルウェアを使用しています – Decept