2
我的令牌缺少刷新和角色屬性。我正在使用OpenIddict。該代碼直到今天仍然有效,它仍然可以在家用電腦上運行,但不能工作。刷新令牌和角色丟失(OpenIddict)
我很確定我做錯了什麼,但由於我比較了startup.cs,AuthorizationController.cs和他們是一樣的(工作和家庭),我需要一些幫助,可能是什麼問題的根源。
我需要爲用戶登錄角色,因爲我的Angular2應用程序需要知道用戶可以在網頁上做什麼。
要求我派:
工作響應:
首頁響應:
的啓動代碼(
services.AddOpenIddict<int>()
.AddEntityFrameworkCoreStores<AppDbContext>()
.AddMvcBinders()
.EnableTokenEndpoint("/API/authorization/token")
.AllowPasswordFlow()
.AllowRefreshTokenFlow()
.UseJsonWebTokens()
.AddEphemeralSigningKey() //todo naj bi bil pravi certifikat, če odstranič to vrstico ne dela in vidiš error.
.SetAccessTokenLifetime(TimeSpan.FromMinutes(30))
.SetRefreshTokenLifetime(TimeSpan.FromDays(14))
.DisableHttpsRequirement();
控制器代碼(又:同一家庭計算機上):再次家用計算機)上相同
public class AuthorizationController : BaseController
{
public AuthorizationController(AppDbContext context, OpenIddictApplicationManager<OpenIddictApplication<int>> applicationManager, SignInManager<AppUser> signInManager, UserManager<AppUser> userManager) : base(context, applicationManager, signInManager, userManager)
{
}
[Authorize, HttpGet("authorize")]
public async Task<IActionResult> Authorize(OpenIdConnectRequest request)
{
Debug.Assert(request.IsAuthorizationRequest(),
"The OpenIddict binder for ASP.NET Core MVC is not registered. " +
"Make sure services.AddOpenIddict().AddMvcBinders() is correctly called.");
// Retrieve the application details from the database.
var application = await applicationManager.FindByClientIdAsync(request.ClientId, HttpContext.RequestAborted);
if (application == null)
{
return View("Error", new ErrorViewModel
{
Error = OpenIdConnectConstants.Errors.InvalidClient,
ErrorDescription = "Details concerning the calling client application cannot be found in the database"
});
}
// Flow the request_id to allow OpenIddict to restore
// the original authorization request from the cache.
return View(new AuthorizeViewModel
{
ApplicationName = application.DisplayName,
RequestId = request.RequestId,
Scope = request.Scope
});
}
[HttpPost("token"), Produces("application/json")]
public async Task<IActionResult> Exchange(OpenIdConnectRequest request)
{
Debug.Assert(request.IsTokenRequest(),
"The OpenIddict binder for ASP.NET Core MVC is not registered. " +
"Make sure services.AddOpenIddict().AddMvcBinders() is correctly called.");
if (request.IsPasswordGrantType())
{
var user = await userManager.FindByNameAsync(request.Username);
if (user == null)
{
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.InvalidGrant,
ErrorDescription = "The email/password couple is invalid."
});
}
// Ensure the user is allowed to sign in.
if (!await signInManager.CanSignInAsync(user))
{
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.InvalidGrant,
ErrorDescription = "The specified user is not allowed to sign in."
});
}
// Reject the token request if two-factor authentication has been enabled by the user.
if (userManager.SupportsUserTwoFactor && await userManager.GetTwoFactorEnabledAsync(user))
{
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.InvalidGrant,
ErrorDescription = "The specified user is not allowed to sign in."
});
}
// Ensure the user is not already locked out.
if (userManager.SupportsUserLockout && await userManager.IsLockedOutAsync(user))
{
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.InvalidGrant,
ErrorDescription = "The username/password couple is invalid."
});
}
// Ensure the password is valid.
if (!await userManager.CheckPasswordAsync(user, request.Password))
{
if (userManager.SupportsUserLockout)
{
await userManager.AccessFailedAsync(user);
}
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.InvalidGrant,
ErrorDescription = "The username/password couple is invalid."
});
}
if (userManager.SupportsUserLockout)
{
await userManager.ResetAccessFailedCountAsync(user);
}
// Create a new authentication ticket.
var ticket = await CreateTicketAsync(request, user);
return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
}
else if (request.IsRefreshTokenGrantType())
{
// Retrieve the claims principal stored in the refresh token.
var info = await HttpContext.Authentication.GetAuthenticateInfoAsync(
OpenIdConnectServerDefaults.AuthenticationScheme);
// Retrieve the user profile corresponding to the refresh token.
var user = await userManager.GetUserAsync(info.Principal);
if (user == null)
{
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.InvalidGrant,
ErrorDescription = "The refresh token is no longer valid."
});
}
// Ensure the user is still allowed to sign in.
if (!await signInManager.CanSignInAsync(user))
{
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.InvalidGrant,
ErrorDescription = "The user is no longer allowed to sign in."
});
}
// Create a new authentication ticket, but reuse the properties stored
// in the refresh token, including the scopes originally granted.
var ticket = await CreateTicketAsync(request, user, info.Properties);
return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
}
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.UnsupportedGrantType,
ErrorDescription = "The specified grant type is not supported."
});
}
private async Task<AuthenticationTicket> CreateTicketAsync(
OpenIdConnectRequest request, AppUser user,
AuthenticationProperties properties = null)
{
// Create a new ClaimsPrincipal containing the claims that
// will be used to create an id_token, a token or a code.
var principal = await signInManager.CreateUserPrincipalAsync(user);
// Note: by default, claims are NOT automatically included in the access and identity tokens.
// To allow OpenIddict to serialize them, you must attach them a destination, that specifies
// whether they should be included in access tokens, in identity tokens or in both.
foreach (var claim in principal.Claims)
{
// In this sample, every claim is serialized in both the access and the identity tokens.
// In a real world application, you'd probably want to exclude confidential claims
// or apply a claims policy based on the scopes requested by the client application.
claim.SetDestinations(OpenIdConnectConstants.Destinations.AccessToken,
OpenIdConnectConstants.Destinations.IdentityToken);
}
// Create a new authentication ticket holding the user identity.
var ticket = new AuthenticationTicket(principal, properties,
OpenIdConnectServerDefaults.AuthenticationScheme);
if (!request.IsRefreshTokenGrantType())
{
// Set the list of scopes granted to the client application.
// Note: the offline_access scope must be granted
// to allow OpenIddict to return a refresh token.
ticket.SetScopes(new[] {
OpenIdConnectConstants.Scopes.OpenId,
OpenIdConnectConstants.Scopes.Email,
OpenIdConnectConstants.Scopes.Profile,
OpenIdConnectConstants.Scopes.OfflineAccess,
OpenIddictConstants.Scopes.Roles
}.Intersect(request.GetScopes()));
}
ticket.SetResources("OpPISWeb"); //also in startup.cs
return ticket;
}
}
對於解碼id_token我使用angular-jwt:
return this.http.post('api/authorization/token', this.encodeObjectToParams(data), options)
.map(res => res.json())
.map((tokens: AuthTokenModel) =>
{
console.log("loged in", tokens);
let now = new Date();
tokens.expiration_date = new Date(now.getTime() + tokens.expires_in * 1000).getTime().toString();
localStorage.setItem('id_token', tokens.access_token);
localStorage.setItem('refresh_token', tokens.refresh_token);
const profile = this.jwtHelper.decodeToken(tokens.id_token) as ProfileModel;
const roles: string[] = typeof profile.role === "string" ? [profile.role] : profile.role;
const userProfile: Profile = new Profile(parseInt(profile.sub), roles);
localStorage.setItem('profile', JSON.stringify(userProfile));
this.refreshTokens(tokens.expires_in * 1000 * 0.8);
return profile;
});
這是一個錯誤,由ASOS(OpenIddict背後的OIDC庫)中最近的格式更改引起的。我現在就在上面,所以期待在接下來的15分鐘裏有一個錯誤修復和一個新的軟件包。 – Pinpoint