#vb.net #asp.net-identity #owin #openid-connect
Вопрос:
У меня есть vb.net приложение, и я сталкиваюсь с этим IDX10501: Проверка подписи не удалась. Не удается сопоставить ключи: проблема. Мой код отлично работает в течение 10-12 часов, но после этого у меня начинает возникать эта проблема .Но как только я повторно сохраню конфигурацию, ничего не меняя, она начнет работать .Затем, через 10-12 часов, я начинаю сталкиваться с той же проблемой. Я предполагаю, что это что-то связанное с подписанием ключей. Любая помощь будет признательна. Я использую OpenAthens.Оуин,Охрана.OpenIdConnect для реализации . Кроме того , даже когда я получаю эту ошибку, я правильно получаю значения Kid и токенов. Файл Startup.vb
Imports System.IdentityModel.Tokens.Jwt
Imports System.Net
Imports System.Net.Http
Imports System.Security.Claims
Imports System.Threading.Tasks
Imports Microsoft.IdentityModel.Protocols
Imports Microsoft.IdentityModel.Protocols.OpenIdConnect
Imports Microsoft.IdentityModel.Logging
Imports Microsoft.IdentityModel.Tokens
Imports Microsoft.Owin.Security
Imports Microsoft.Owin.Security.Cookies
Imports Newtonsoft.Json
Imports OpenAthens.Owin.Security.OpenIdConnect
Imports Owin
Public Class ExpectedJwksResponse
<JsonProperty(PropertyName:="keys")>
Public Property Keys As List(Of JsonWebKey)
End Class
Public Class Startup
Private ReadOnly clientId As String = ConfigurationManager.AppSettings("ClientId")
Private ReadOnly authority As String = ConfigurationManager.AppSettings("OrgUri")
Private ReadOnly clientSecret As String = ConfigurationManager.AppSettings("ClientSecret")
Private ReadOnly redirectUri As String = ConfigurationManager.AppSettings("RedirectUri")
Private ReadOnly callBackPath As String = ConfigurationManager.AppSettings("CallBackPath")
Private ReadOnly acr As String = ConfigurationManager.AppSettings("Acr")
Private ReadOnly acrValues As String = ConfigurationManager.AppSettings("AcrValues")
Public Sub Configuration(ByVal app As IAppBuilder)
ConfigureAuth(app)
End Sub
Public Sub ConfigureAuth(ByVal app As IAppBuilder)
Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Dim configurationManager = New ConfigurationManager(Of OpenIdConnectConfiguration)(
$"{authority}/.well-known/openid-configuration",
New OpenIdConnectConfigurationRetriever(), New HttpDocumentRetriever())
Dim discoveryDocument = configurationManager.GetConfigurationAsync().Result
Dim signingKeys = GetSecurityKeyAsync(discoveryDocument.JwksUri).Result
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType)
IdentityModelEventSource.ShowPII = True
app.UseCookieAuthentication(New CookieAuthenticationOptions())
app.UseOpenIdConnectAuthentication(New OpenIdConnectAuthenticationOptions With {
.GetClaimsFromUserInfoEndpoint = True,
.ClientId = clientId,
.ClientSecret = clientSecret,
.Authority = authority,
.ResponseType = OpenIdConnectResponseType.Code,
.RedirectUri = redirectUri,
.CallbackPath = Microsoft.Owin.PathString.FromUriComponent(New Uri(callBackPath)),
.TokenValidationParameters = New TokenValidationParameters() With {
.IssuerSigningKeys = signingKeys,
.RequireSignedTokens = True,
.RequireExpirationTime = True,
.ValidateLifetime = True,
.ValidateAudience = True,
.ValidAudience = clientId,
.ValidateIssuer = True,
.ValidIssuer = authority,
.SaveSigninToken = True
},
.Notifications = New OpenIdConnectAuthenticationNotifications With {
.RedirectToIdentityProvider = Function(n)
n.ProtocolMessage.SetParameter(acr, acrValues)
n.Response.Redirect(callBackPath)
n.ProtocolMessage.RedirectUri = callBackPath
Return Task.FromResult(0)
End Function,
.SecurityTokenValidated = Function(context)
Dim anc = Convert.ToString(context.ProtocolMessage.AccessToken)
Dim rawAccessToken As String = context.ProtocolMessage.AccessToken
Dim rawIdToken As String = context.ProtocolMessage.IdToken
Dim handler = New JwtSecurityTokenHandler()
Dim accessToken = handler.ReadJwtToken(rawAccessToken)
Dim idToken = handler.ReadJwtToken(rawIdToken)
context.Response.Redirect(callBackPath)
If (TypeOf context.AuthenticationTicket.Identity Is ClaimsIdentity) Then
Dim identity As ClaimsIdentity = New ClaimsIdentity
Dim claimsIdentity As ClaimsIdentity = CType(context.AuthenticationTicket.Identity, ClaimsIdentity)
Dim userId As String = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier).Value
identity.AddClaim(New Claim(ClaimTypes.GivenName, userId))
End If
Return Task.CompletedTask
End Function
}
})
End Sub
Private Async Function GetSecurityKeyAsync(ByVal jwksUri As String) As Task(Of List(Of SecurityKey))
Using client = New HttpClient()
Dim response = Await client.GetAsync(New Uri(jwksUri))
If response.IsSuccessStatusCode Then
Dim result = Await response.Content.ReadAsAsync(Of ExpectedJwksResponse)()
Dim keys = New List(Of SecurityKey)()
Dim i = 0
For Each key In result.Keys
keys.Add(key)
i = i 1
Next
Return keys
End If
End Using
Return Nothing
End Function
End Class
Вызов :
HttpContext.Current.GetOwinContext().Authentication.Challenge(New AuthenticationProperties With {
.RedirectUri = ConfigurationManager.AppSettings("RedirectUri")}, OpenIdConnectAuthenticationDefaults.AuthenticationType)
Комментарии:
1. Какой сервер авторизации вы используете? видите ли вы это в производстве или локально во время разработки?
2. Это никогда не приходит локально, но приходит в dev , stage и prod. Сервер аутентификации-это наш внутренний сервер аутентификации компании.
Ответ №1:
В процессе производства вам необходимо решить несколько различных проблем:
- Ключ подписи токена IdentityServer должен быть настроен и сохранен за пределами вашей службы, чтобы он оставался неизменным во время перераспределения.
- API защиты данных в каждом ASP.NET Основная служба должна быть настроена таким образом, чтобы ключ шифрования и связка ключей сохранялись. Так что то же самое происходит и во время перераспределения. Вам нужно сделать это, чтобы все выданные файлы cookie принимались после перераспределения.
Комментарии:
1. не могли этого понять ? Мое приложение не требует передислокации . Даже после того, как я перезапущу приложение, оно начнет работать.
2. одно дело-следить за ключами здесь, они все время одинаковые или меняются через 10-12 часов? ваш сервер/.известный/openid-конфигурация/jwks
3. Как он внедряется в производство?
4. Он меняется с сервера аутентификации, но я не могу каждый раз получать последний ключ. Всякий раз , когда приложение запускается впервые на сервере, оно получает ключи. Я не могу найти способ, как получить новый ключ с сервера . Как и этот метод вызова , не вызывайте тот шаг, на котором вы получаете ключ подписи.
5. если у вас в классе запуска в рабочей среде есть эта инструкция «AddDeveloperSigningCredential()» , то вам нужно выполнить некоторую работу.