(1)identityserver4授權服務器端
public static class Config
{
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new IdentityResource[]
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Email(),
new IdentityResources.Phone(),
new IdentityResources.Address(),
};
}
public static IEnumerable<ApiResource> GetApis()
{
return new ApiResource[]
{
new ApiResource("api1", "My API #1")
};
}
public static IEnumerable<Client> GetClients()
{
return new[]
{
new Client
{
ClientId="mvc client",
ClientName="ASP.NET Core MVC Client",
AllowedGrantTypes=GrantTypes.CodeAndClientCredentials,
ClientSecrets={new Secret( "mvc secret".Sha256())},
RedirectUris={"http://localhost:5002/signin-oidc"},
FrontChannelLogoutUri="http://localhost:5002/signout-oidc",
PostLogoutRedirectUris={"http://localhost:5002/signout-callback-oidc"},
AlwaysIncludeUserClaimsInIdToken=true,//將用戶所有的claims包含在IdToken內
AllowOfflineAccess=true,//offline_access,其實指的是能否用refreshtoken重新申請令牌
AllowedScopes =
{
"api1",
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Address,
IdentityServerConstants.StandardScopes.Phone,
IdentityServerConstants.StandardScopes.Email
}
}
};
}
}
(2)客戶端,還是需要安裝IdentityModel庫,
在startup.cs的ConfigurServices一節,需要做如下添加:
//關閉默認映射,否則它可能修改從授權服務返回的各種claim屬性
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
//添加認證服務,並設置其有關選項
services.AddAuthentication(options =>
{
//客戶端應用設置使用"Cookies"進行認證
options.DefaultScheme =CookieAuthenticationDefaults.AuthenticationScheme ;
//identityserver4設置使用"oidc"進行認證
options.DefaultChallengeScheme =OpenIdConnectDefaults.AuthenticationScheme ;
}).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
//對使用的OpenIdConnect進行設置,此設置與Identityserver的config.cs中相應client配置一致才可能登錄授權成功
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options=> {
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ClientId = "mvc client";
options.ClientSecret = "mvc secret";
options.SaveTokens = true;
options.ResponseType = "code";
options.Scope.Clear();
options.Scope.Add("api1");
options.Scope.Add(OidcConstants.StandardScopes.OpenId);//"openid"
options.Scope.Add(OidcConstants.StandardScopes.Profile);//"profile"
options.Scope.Add(OidcConstants.StandardScopes.Address);
options.Scope.Add(OidcConstants.StandardScopes.Email);
options.Scope.Add(OidcConstants.StandardScopes.Phone);
// 與identity server的AllowOfflineAccess=true,對應。offline_access,指的是能否用refreshtoken重新申請令牌
options.Scope.Add(OidcConstants.StandardScopes.OfflineAccess);
});
在Confiure一節,app.UseMvc之前添加如下內容:
app.UseAuthentication();
然后,在controller中使用時,按如下方式: 通常需如下引用
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using MvcClient.Models;
//獲取AccessToken、IdToken、RefreshToken時:
[Authorize]
public async Task<IActionResult> Privacy()
{
var accessToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken);
var idToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.IdToken);
var refreshToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.RefreshToken);
var authorizationCode = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.Code);
ViewData["idToken"] = idToken;
ViewData["refreshToken"] = refreshToken;
ViewData["accessToken"] = accessToken;
return View();
}
//訪問Api資源時
public async Task<IActionResult> AccessApi()
{
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5000");
ViewData["disco"] = disco.Error;
if (disco.IsError)
{
ViewData["disco"] = disco.Error;
return View();
}
var accessToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken);
client.SetBearerToken(accessToken);
var response = await client.GetAsync("http://localhost:5001/api/values");
if (!response.IsSuccessStatusCode)
{
ViewData["response_error"] = response.StatusCode;
return View();
}
ViewData["response-content"] = await response.Content.ReadAsStringAsync();
return View();
}
從客戶端及identityserver4登出時:
public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);
return View();
}
如果登出需要跳轉回到客戶端應用網站,則需在將IdentityServer4的命名空間IdentityServer4.Quickstart.UI下的AccountOptions類中
public static bool AutomaticRedirectAfterSignOut = true;
這樣,從identityserver登出后,將自動跳轉到客戶應用頁面。