2017-06-11 131 views
5

我想與碼頭配置IdentityServer4,但我不能讓它工作。要開始,我拿着身份證服務器文檔的客戶機憑證例如:Protecting an API using Client Credentials身份服務器4和碼頭

IdentityServer
託管端口5000

的WebAPI
託管端口5001

Configure我的WebApi的Startup.cs文件的方法我做了以下(問題可能在這裏):

app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions 
     { 
      Authority = "http://web:5000",     
      RequireHttpsMetadata = false, 
      ApiName = "api1" 
     }); 

客戶
而客戶端

// Everything is fine here... 
var disco = await DiscoveryClient.GetAsync("http://localhost:5000"); 
var tokenClient = new TokenClient(disco.TokenEndpoint, "client", "secret"); 
var tokenResponse = await tokenClient.RequestClientCredentialsAsync("api"); 

// This does not work 
var client = new HttpClient(); 
client.SetBearerToken(tokenResponse.AccessToken); 
var response = await client.GetAsync("http://localhost:5001/identity"); 

這個問題可能是在我的WebAPI:

1)如果我設置的權限爲localhost:5000,我得到一個內部服務器錯誤:「無法獲取配置:'http://localhost:5000/.well-known/openid-configuration'」這是有道理的,因爲localhost:5000在這個容器中是未知的

2)如果我將權限設置爲http://web:5000,我收到一個授權錯誤:「頒發者驗證失敗。發行人:'http://localhost:5000'。不符合:validationParameters.ValidIssuer:'http://web:5000'或validationParameters.ValidIssuers「這也有道理,但我不知道是否有可能更改權威名稱?我也嘗試在IdentityServer項目中設置IssuerUri,但它沒有'牛逼的幫助

回答

5

網絡

讓我們假設你有兩個物理機:C1和C2每臺機器是一個碼頭工人主機

C1運行驗證容器

C2運行的WebAPI containe。河

當您在Auth dockerfile中公開端口5000時,應該可以從WebApi容器本身的C2 訪問地址C1:5000。你可能更喜歡IP到DNS,這沒關係。此外,您應該能夠成功地獲得成功的http://C1:5000/.well-known/openid-configuration GET請求。

您可能需要面對很多網絡問題才能做到這一點。例如: What would prevent code running in a Docker container from connecting to a database on a separate server?

發行人確認

Issuer validation failed

您的客戶端的權限從URL驗證主機名不同。默認情況下,授權URL應等於issuer屬性值(此屬性位於Identity Server自動發現文檔響應中)。

issuer屬性值取決於客戶端的Web請求:

GET http://127.0.0.1:6000/.well-known/openid-configuration -> "issuer": "http://127.0.0.1:6000" 
GET http://localhost:6000/.well-known/openid-configuration -> "issuer": "localhost:6000" 

嘗試設置IssuerUri以恆定的開發環境:

services.AddIdentityServer(x => 
{ 
    x.IssuerUri = "foo"; 
}) 

實現恆定issuer值。這allowes通過任何有效的URL(使用IP,機器名或DNS)來調用身份服務器:

GET http://anything/.well-known/openid-configuration -> "issuer": "foo" 

DiscoveryClient也驗證issuer值。這是一個簡單的平等comparison

public bool ValidateIssuerName(string issuer, string authority) 
{ 
    return string.Equals(issuer, authority, StringComparison.Ordinal); 
} 

您可以通過禁用它:

DiscoveryClient.Policy.ValidateIssuerName = false; 

僅供參考,IssuerUri用於生產環境設置is not recommended

IssuerUri Set the issuer name that will appear in the discovery document and the issued JWT tokens. It is recommended to not set this property, which infers the issuer name from the host name that is used by the clients.

+0

這樣做打破的第一部分我client:var disco = await DiscoveryClient.GetAsync(「http:// localhost:5000」);得到以下異常:錯誤=「發行人名稱不符合權威:foo」'見我的編輯更多信息 – Bidou

+0

@Bidou你確定它是正確的嗎? 'DiscoveryClient.GetAsync'只是一個GET請求並解析響應。並且在發行者名稱變化之後,所有的令牌必須由新的代替。 –

+0

其實它有點we。。如果我檢查'GetAsync'返回的'DiscoveryResponse',我可以看到'Raw'屬性具有json響應集(例如'issuer'和'tokenendpoint'),但是'Error'屬性包含上面提到的消息「頒發者名稱與權限:foo不匹配」。 TokenEndpoint屬性爲空(即使它在原始json中),然後發生NullPointerException,因爲下一行使用此屬性來置換TokenClient .... – Bidou