2017-04-14 61 views
0

我正在編寫IdentityServer4實現並使用快速入門項目here爲什麼我在IdentityServer4的同意屏幕上看到重複的範圍?

當您定義一個ApiResource(現在使用InMemory類)時,它看起來像IdentityServer創建一個與資源同名的Scope。例如

public static IEnumerable<ApiResource> GetApiResources() 
{ 
    return new List<ApiResource> 
    { 
     new ApiResource("api", "My API") 
    }; 
} 

將創建一個名爲「API」的範圍(這是在ApiResource構造函數中完成的)。如果我在客戶端對象上使用「api」作爲允許的範圍(使用InMemoryClients作爲概念證明),並在我的JavaScript客戶端的身份驗證請求中的作用域查詢字符串參數中請求此作用域,我會收到invalid_scope錯誤消息。

我發現以下this documentation您可以通過作用域屬性,像這樣

new ApiResource 
{ 
    Name = "api", 
    DisplayName = "Custom API", 
    Scopes = new List<Scope> 
    { 
      new Scope("api.read"), 
      new Scope("api.write") 
     } 
} 

添加作用域到ApiResource所以現在,如果我不是定義我ApiResource這樣並請求作用域api.read和api.write (並將它們添加到客戶端對象上的AllowedScopes屬性),那麼一切正常,除了顯示重複範圍的同意頁面。它顯示了2次api.read和api.write 2次。看到這裏

enter image description here

同意畫面客戶端配置如下:

new Client 
{ 
    ClientId = "client.implicit", 
    ClientName = "JavaScript Client", 
    AllowedGrantTypes = GrantTypes.Implicit, 
    AllowAccessTokensViaBrowser = true, 
    RedirectUris = { "http://localhost:3000/health-check" }, 
    PostLogoutRedirectUris = { "http://localhost:3000" }, 
    AllowedCorsOrigins =  { "http://localhost:3000" }, 
    AllowedScopes = { 
         IdentityServerConstants.StandardScopes.OpenId, 
         IdentityServerConstants.StandardScopes.Profile, 
         "customApi.read", "customApi.write" 
        } 
} 

這究竟是爲什麼?我做了什麼明顯錯誤?

更新: 這裏發現的文件,顯示範圍是隻列出一次的一部分...

enter image description here

+0

你有多少API資源?他們的範圍將被複制。請考慮從'/ .well-known/openid-configuration'端點發布'scopes_supported'內容。 –

+0

@IlyaChumakov我發佈了它。我絕對只有一個API資源,所以我迷失在爲什麼會發生這種情況 –

回答

1

它看起來像問題是與快速入門用戶界面..或者與Scope.cs類取決於你如何看待它。具體而言,在該方法和線在類ConsentService.cs

以下代碼

vm.ResourceScopes = resources.ApiResources.SelectMany(x => x.Scopes).Select(x => CreateScopeViewModel(x, vm.ScopesConsented.Contains(x.Name) || model == null)).ToArray(); 

所示未過濾掉的重複。也就是說,即使兩個範圍具有相同的名稱,但它們並不相同。因此,如果在Scope.cs(它位於IdentityServer4中 - 不是快速入門)中覆蓋GetHashCodeEquals,那麼它將解決此問題。在這種情況下,SelectMany會返回一個唯一的集合。這是因爲ApiResources屬性是作爲HashSet實現的。或者,您可以編寫自己的邏輯,使其返回一組唯一的範圍。這就是我解決問題的方法。我寫了一些與Jon Skeet在this post中的回答非常相似的東西,它們濾除了重複的範圍。

1

問題在於IdentityService4代碼在執行InMemoryResourcesStore.FindApiResourcesByScopeAsync中,並且使用此commit修復了此問題。您可以在2017年6月22日以後使用dev分支,但它從未在任何針對.NET Standard 1.4的NuGET軟件包中發佈,這非常煩人。

我創建了一個問題,並要求它來獲取補丁: https://github.com/IdentityServer/IdentityServer4/issues/1470

對於固定的看法,我說標有藤行至ConsentService.cs

var resources = await _resourceStore.FindEnabledResourcesByScopeAsync(request.ScopesRequested); 
if (resources != null && (resources.IdentityResources.Any() || resources.ApiResources.Any())) 
{ 
    // TODO: Hotfix to cleanup scope duplication: 
    resources.ApiResources = resources.ApiResources.DistinctBy(p => p.Name).ToList(); 
    return CreateConsentViewModel(model, returnUrl, request, client, resources); 
} 

這解決了顯示問題,但範圍仍然會在訪問令牌中被多次包含,因爲它會調整該API的範圍計數。我有3個範圍,所以每個包含3次,增加6個不需要的範圍副本。但至少它是可用的,直到它被修復。