にリダイレクトをトリガーするアプリケーションAがIdentityServerからの復帰時に読むことができるあなたにreturnurlにおけるいくつかのカスタムパラメータを含めることができます
- アプリケーションA(IDプロバイダ)でユーザーを認証
- トークンエンドポイントと共有秘密情報を使用してIdentity Server 4からアクセストークンを取得します。
- リダイレクト時にヘッダーが保持されないため、クエリトークンパラメータとしてアクセストークンを追加します。
- ユーザーを、usernameなどの識別情報を受け付けるアカウントコントローラメソッドにリダイレクトします。このメソッドは、アクセストークンパラメータのクエリ文字列をチェックするカスタムミドルウェアクラスによって保護されています。トークンが存在する場合、トークンは認証ヘッダーに追加されます。これは、このコントローラメソッドにヒットすることをユーザーに許可します。
- コントローラーメソッドは、ユーザーに署名し、エンドポイント
/connect/authorize/login
にリダイレクトします。
- 最後に、ログインエンドポイントは、クッキーを設定し、URL
redirect_uri
クエリパラメータで指定されたアプリケーションB(サービスプロバイダ)、にユーザーをリダイレクトします。共有シークレットのため
構成:
クライアントに適切な許可タイプ、秘密と新しいスコープ名を追加します。新しいスコープは、ログ内のアクセストークンの問題のデバッグに役立ちます(特に、複数のアプリケーションがID4サーバーに当たる場合)。また、サービスプロバイダのURLをクライアントRedirectUrisに追加してください。そうしないと、「無効なリダイレクト」エラーが表示されます。
AllowedGrantTypes = new List<string> { GrantType.Implicit, GrantType.ClientCredentials },
ClientSecrets = new List<Secret> {
new Secret(_clientSecrets.ExternalIdpSecret.Sha256(), clientID)
},
AllowedScopes = new List<string>
{
"newScopeName"
},
RedirectUris = new List<string>
{
$"http://localhost:<portnumber>"
}
次に、カスタムミドルウェアを追加します。
public class QueryStringOAuthBearerMiddleware
{
private readonly RequestDelegate next;
public QueryStringOAuthBearerMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
this.BeginInvoke(context);
await this.next.Invoke(context);
this.EndInvoke(context);
}
private void BeginInvoke(HttpContext context)
{
if (context.Request.Query.ContainsKey("accesstokenparametername"))
{
var accessToken = context.Request.Query.First(p => p.Key == "accesstokenparametername");
if (!string.IsNullOrEmpty(accessToken.Value))
{
context.Request.Headers.Add("Authorization", "Bearer " + accessToken.Value);
}
}
}
private void EndInvoke(HttpContext context)
{
}
}
設定にミドルウェアを追加します。
app.UseMiddleware<QueryStringOAuthBearerMiddleware>();
ログイン方法を作成します。クライアントアプリケーションのための
[HttpGet]
[Authorize]
public async Task<IActionResult> Login2(string userName, string returnURL)
{
await _httpContextWrapper.SignInAsync(userName);
return Redirect(returnURL);
}
構成(IDP):
次のようになりますあなたのクライアント側のコード:
var disco = await DiscoveryClient.GetAsync("http://localhost:<portnumber>");
var tokenClient = new TokenClient(disco.TokenEndpoint, "clientIdentifier", "IUsedAGuidHere");
var tokenResponse = await tokenClient.RequestClientCredentialsAsync("newScopeName");
var redirectURL = string.Format("http://localhost:2228/account/Login2?userName=<UserIDValue>&returnURL={1}&accesstokenparametername={0}",
tokenResponse.AccessToken,
Server.UrlEncode(
string.Format("/connect/authorize/login?client_id={3}&redirect_uri={2}&response_type=id_token%20token&scope=<ImplicitFlowScopes>&state={0}&nonce={1}",
CryptoRandom.CreateUniqueId(),
CryptoRandom.CreateUniqueId(),
Server.UrlEncode("http://localhost:<PortNumber>"),
"ClientIdentifier")));
Response.Redirect(redirectURL, false);
注:これを取ることができなくなりますのでご了承下さいAS-ISをコード化して動作させる。私はリソースのセキュリティを保護するために大きく変更しました。
アプリケーションAとBは* ClientSecrets *で同じ* Secret *を共有していますか? @alan – Babak
@BabakアプリケーションBは、その懸念がOAuthトークンであるため、ClientSecretを活用しません。簡単に言えば、アプリケーションAはClientSecretを使用してOAuthトークンを取得し、そのトークンをアプリケーションBに提示します。 – alan
しかし、認証アプリケーションはトークンを受け入れず、Login2()に入ります。どんな意見ですか? – Babak