IdentityServer3에 의해 보호되는 API에서 리소스에 액세스하려고하면 401 오류가 발생합니다.IdentityServer3에 의해 보호되는 API에 액세스 할 때 오류 401
나는 로그인 IdentityServer3의 호스트 응용 프로그램에서 조용히 access_token이를 얻을 수 있지만이 자원을 소비 access_token이 를 사용할 수 있습니다.
나는 클래스 같은 시작에 IdentityServer 내 호스트를 구성 : 내 ServiceFactory 클래스에서public void Configuration(IAppBuilder app)
{
Log.Logger = new LoggerConfiguration()
.WriteTo.Trace()
.CreateLogger();
AntiForgeryConfig.UniqueClaimTypeIdentifier = Constants.ClaimTypes.Subject;
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
// Configure IdentityServer3
app.Map("/identity", configuration =>
{
configuration.UseIdentityServer(new IdentityServerOptions
{
SiteName = "IdentityServer3 Sample",
SigningCertificate = LoadCertificate(),
Factory = ServiceFactory.Create(),
RequireSsl = true,
CspOptions = new CspOptions
{
Enabled = true,
FontSrc = "fonts.googleapis.com"
},
AuthenticationOptions = new AuthenticationOptions
{
EnablePostSignOutAutoRedirect = true,
}
});
});
}
, 내가 가진 :
public static IdentityServerServiceFactory Create()
{
var factory = new IdentityServerServiceFactory
{
ScopeStore = new Registration<IScopeStore>(
new InMemoryScopeStore(Scopes.GetScopes())),
ClientStore = new Registration<IClientStore>(
new InMemoryClientStore(Clients.GetClients())),
CorsPolicyService = new Registration<ICorsPolicyService>(
new DefaultCorsPolicyService {AllowAll = true})
};
//factory.UseInMemoryUsers(Users.GetUsers());
ConfigureServices(factory);
return factory;
}
private static void ConfigureServices(IdentityServerServiceFactory factory)
{
factory.UserService = new Registration<IUserService, UserService>();
factory.Register(new Registration<BaseContext>(resolver => new BaseContext()));
factory.Register(new Registration<AppUserManager>(resolver => new AppUserManager(
new UserStore<User>(resolver.Resolve<BaseContext>()))));
}
스코프를을 :
(210)return new List<Scope>
{
StandardScopes.OpenId,
StandardScopes.Profile,
StandardScopes.OfflineAccess,
new Scope
{
Enabled = true,
Name = "roles",
Type = ScopeType.Identity,
IncludeAllClaimsForUser = true,
Claims = new List<ScopeClaim>
{
new ScopeClaim("role")
}
},
new Scope
{
Enabled = true,
Name = "ro",
Type = ScopeType.Resource,
IncludeAllClaimsForUser = true,
Claims = new List<ScopeClaim>
{
new ScopeClaim("role")
}
}
};
그리고 클라이언트는 :
return new List<Client>
{
new Client
{
Enabled = true,
ClientName = "Hibrid Flow Client",
ClientId = AppIdentityConstants.ClientIdForHibridFlow,
Flow = Flows.Hybrid,
RequireConsent = false,
AccessTokenType = AccessTokenType.Reference,
UpdateAccessTokenClaimsOnRefresh = true,
ClientSecrets = new List<Secret>
{
new Secret(AppIdentityConstants.ClientSecret.Sha256())
},
AllowedScopes = new List<string>
{
Constants.StandardScopes.OpenId,
Constants.StandardScopes.Profile,
Constants.StandardScopes.Email,
Constants.StandardScopes.Roles,
Constants.StandardScopes.OfflineAccess,
},
RedirectUris = new List<string>
{
AppIdentityConstants.IdentityAddress,
AppIdentityConstants.CRMAddress
},
PostLogoutRedirectUris = new List<string>
{
AppIdentityConstants.IdentityAddress,
AppIdentityConstants.CRMAddress
},
LogoutSessionRequired = true
},
new Client
{
Enabled = true,
ClientName = "Resource Owner Client",
ClientId = AppIdentityConstants.ClientIdForResourceOwnerFlow,
Flow = Flows.ResourceOwner,
RequireConsent = false,
AccessTokenType = AccessTokenType.Jwt,
UpdateAccessTokenClaimsOnRefresh = true,
AccessTokenLifetime = 3600,
ClientSecrets = new List<Secret>
{
new Secret(AppIdentityConstants.ClientSecret.Sha256())
},
AllowedScopes = new List<string>
{
Constants.StandardScopes.OpenId,
Constants.StandardScopes.Profile,
Constants.StandardScopes.Email,
Constants.StandardScopes.Roles,
Constants.StandardScopes.OfflineAccess,
"ro"
},
AllowAccessTokensViaBrowser = true,
AbsoluteRefreshTokenLifetime = 86400,
SlidingRefreshTokenLifetime = 43200,
RefreshTokenUsage = TokenUsage.OneTimeOnly,
RefreshTokenExpiration = TokenExpiration.Sliding
},
};
이 IdentityServer3의 호스트 응용 프로그램의 소스 코드입니다.
이제 API를 어떻게 설정했는지 보여 드리겠습니다.
public void Configuration(IAppBuilder app)
{
JwtSecurityTokenHandler.InboundClaimTypeMap.Clear();
app.UseIdentityServerBearerTokenAuthentication(
new IdentityServerBearerTokenAuthenticationOptions
{
Authority = AppIdentityConstants.IdentityBaseAddress,
RequiredScopes = new[] { "ro", "offline_access" },
ClientId = AppIdentityConstants.ClientIdForResourceOwnerFlow,
ClientSecret = AppIdentityConstants.ClientSecret,
});
}
AppIdentityConstants.IdentityBaseAddress
가 https://localhost:44342/identity
입니다 : 이 클래스 내 시작이다.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.Formatters.Remove(config.Formatters.XmlFormatter);
var formatters = GlobalConfiguration.Configuration.Formatters;
var jsonFormatter = formatters.JsonFormatter;
var settings = jsonFormatter.SerializerSettings;
#if DEBUG
settings.Formatting = Formatting.Indented;
#endif
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
// Web API routes
config.MapHttpAttributeRoutes();
config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
그리고 AuthorizeAttribute을 필터 :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<script src="bower_components/jquery/dist/jquery.min.js"></script>
<script>
function done(response) { console.log(response); }
function always(response) { console.log("always"); }
function fail(response) { console.log("fail"); }
var custom = {
client_id: "ro",
client_secret: "client_secret",
scope: "ro offline_access",
};
$(function() {
var settings = {
"async": true,
"crossDomain": true,
"url": "https://localhost:44342/identity/connect/token",
"method": "POST",
"headers": {
"content-type": "application/x-www-form-urlencoded",
"cache-control": "no-cache"
},
"data": {
"client_id": custom.client_id,
"client_secret": custom.client_secret,
"scope": custom.scope,
"username": "[email protected]",
"password": "123456",
"grant_type": "password"
}
}
$.ajax(settings).done(function (response){
done(response);
checkStatus(response.access_token);
}).always(always).fail(fail);
function checkStatus(access_token) {
var settings2 = {
"async": true,
"crossDomain": true,
"url": "https://localhost:44352/api/importer/status",
"method": "GET",
xhrFields: {
withCredentials: true
},
"headers": {
"Authorization": "Bearer " + access_token,
"cache-control": "no-cache"
}
}
$.ajax(settings2).done(done).always(always).fail(fail);
}
});
</script>
</body>
</html>
: public class FilterConfig
{
public static void RegisterGlobalFilters(HttpConfiguration configuration)
{
configuration.Filters.Add(new AuthorizeAttribute());
}
}
내가 다음 않았다 테스트하려면
acess_token을 포함하여 액세스 데이터를 얻는 첫 번째 요청이 성공적으로 완료됩니다.
그러나 API에 대해 수행 된 두 번째 요청은 401 오류를 반환합니다.
앞에서 설명한 것처럼 API는 AuthorizeAttribute으로 보호됩니다.
무엇이 잘못 되었나요?
'Microsoft.Owin.Host.SystemWeb'의 설치가 효과적입니다. 하지만'WWW-Authenticate → Bearer error = "insufficient_scope"오류가 발생합니다. 무슨 일이 일어날 지 아십니까? 너 나 좀 도와 줄 수있어? – JamesTK
간단히 말해서,'IdentityServerBearerTokenAuthenticationOptions'의'RequiredScopes' 속성은 배열이고 하나의 온라인 범위를 알려주고있었습니다. 해결! – JamesTK