このチュートリアルに基づいて http://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server 、承認サーバー、リソースを作成しましたサーバーとMVCクライアント。 MVCクライアントには、リソースサーバーからデータを取得するコントローラーがあります。リソースサーバーには認証が必要です。 MVCクライアントは、認証サーバーから認証コードを取得し、認証のためにユーザーを認証サーバーにリダイレクトします。最後に、MVCクライアントは、アクセストークンの認証コードを交換してリソースサーバーにアクセスします。これは、OAuth 2プロトコルで説明されている認証コードフローです。これは正常に機能します。
これで、MVCクライアント自体のコントローラーに認証を要求させる必要があります。このためのチュートリアルが見つかりません。
追加した
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
私のStartup.Auth.csに。承認サーバーにリダイレクトするオプションを設定する必要があると思います。オプションでプロバイダーを設定することもできます。
app.UseOAuthBearerAuthentication(new Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationOptions()
{
Provider = new OAuthBearerAuthenticationProvider()
});
しかし、私はプロバイダーのイベントの実装にも固執しています。誰かが私を正しい方向に導くことができますか?または私を助けるかもしれないチュートリアルはありますか?
私はブロックアレンからのこれらの2つの記事に基づいた解決策に行き着きました:
基本的な考え方は、2つの認証ミドルウェアを登録することです。アクティブなCookie-AuthenticationとパッシブなOAuthBearer-Authentication。 Startup.Auth.csでは、次のように追加されます。
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/ExternalLogin/Login"),
});
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
{
AuthenticationType = DefaultAuthenticationTypes.ExternalBearer,
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Passive,
});
また、ExternalLogin-Controllerを追加します。そのLoginメソッドは、認証コードを取得するために、ユーザーを認証サーバーのログインページにリダイレクトする必要があります。認証コードを処理するコールバック関数を提供する必要があります。
public async Task<ActionResult> Login(string returnUrl)
{
if (string.IsNullOrEmpty(returnUrl) && Request.UrlReferrer != null)
returnUrl = Server.UrlEncode(Request.UrlReferrer.PathAndQuery);
if (Url.IsLocalUrl(returnUrl) && !string.IsNullOrEmpty(returnUrl))
_returnUrl = returnUrl;
//callback function
_redirectUrl = Url.Action("AuthorizationCodeCallback", "ExternalLogin", null, Request.Url.Scheme);
Dictionary<string, string> authorizeArgs = null;
authorizeArgs = new Dictionary<string, string>
{
{"client_id", "0123456789"}
,{"response_type", "code"}
,{"scope", "read"}
,{"redirect_uri", _redirectUrl}
// optional: state
};
var content = new FormUrlEncodedContent(authorizeArgs);
var contentAsString = await content.ReadAsStringAsync();
return Redirect("http://localhost:64426/oauth/authorize?" + contentAsString);
}
コールバック関数では、認証コードをアクセストークン(および更新トークン)と交換して、パッシブOAuthBearer-authenticationミドルウェアにチャレンジし、AccessトークンをCookieとして使用してサインインします。
public async Task<ActionResult> AuthorizationCodeCallback()
{
// received authorization code from authorization server
string[] codes = Request.Params.GetValues("code");
var authorizationCode = "";
if (codes.Length > 0)
authorizationCode = codes[0];
// exchange authorization code at authorization server for an access and refresh token
Dictionary<string, string> post = null;
post = new Dictionary<string, string>
{
{"client_id", "0123456789"}
,{"client_secret", "ClientSecret"}
,{"grant_type", "authorization_code"}
,{"code", authorizationCode}
,{"redirect_uri", _redirectUrl}
};
var client = new HttpClient();
var postContent = new FormUrlEncodedContent(post);
var response = await client.PostAsync("http://localhost:64426/token", postContent);
var content = await response.Content.ReadAsStringAsync();
// received tokens from authorization server
var json = JObject.Parse(content);
_accessToken = json["access_token"].ToString();
_authorizationScheme = json["token_type"].ToString();
_expiresIn = json["expires_in"].ToString();
if (json["refresh_token"] != null)
_refreshToken = json["refresh_token"].ToString();
//SignIn with Token, SignOut and create new identity for SignIn
Request.Headers.Add("Authorization", _authorizationScheme + " " + _accessToken);
var ctx = Request.GetOwinContext();
var authenticateResult = await ctx.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ExternalBearer);
ctx.Authentication.SignOut(DefaultAuthenticationTypes.ExternalBearer);
var applicationCookieIdentity = new ClaimsIdentity(authenticateResult.Identity.Claims, DefaultAuthenticationTypes.ApplicationCookie);
ctx.Authentication.SignIn(applicationCookieIdentity);
var ctxUser = ctx.Authentication.User;
var user = Request.RequestContext.HttpContext.User;
//redirect back to the view which required authentication
string decodedUrl = "";
if (!string.IsNullOrEmpty(_returnUrl))
decodedUrl = Server.UrlDecode(_returnUrl);
if (Url.IsLocalUrl(decodedUrl))
return Redirect(decodedUrl);
else
return RedirectToAction("Index", "Home");
}
これが、MVC5アプリケーションでOAuth認証コードフローを実装している人に役立つことを願っています。
私は公式サンプルを使用しました MVC Implicit Client これはMVCアプリケーションの正しい認証フローであると私は信じています。
承認のために私はこれを使用しました はじめに 、特にロールが指定されている場合の無限ループに関する部分[Authorize(Roles = "Foo,Bar")]
で、ユーザーは認証されていますが、これらのいずれも所有していません。