は私が記事のようにほぼ正確にそれを実装しました記事OAuthAuthorizationServerProviderはどこでRefresh Token Expiryをチェックしますか?
次認証サーバを実装しているが、私は、認証サーバは、リフレッシュトークンの有効期限が切れている知っている方法を見てはいけません。確かに私はテストしたが、サーバーは期限切れのリフレッシュトークンが表示されたときにアクセストークンを許可しませんが、私の認証サーバーではこのロジックが表示されません。さらに、期限切れリフレッシュトークンを使用してアクセストークンを要求すると、私のOAuthAuthorizationServerProviderサブクラスは決して呼び出されません。期限切れの新しいアクセストークンを要求すると、実際にOAuthAuthorizationServerProvider派生クラスまたはIAuthenticationTokenProvider実装のメソッドは呼び出されませんリフレッシュトークン。どんな助けもありがとうございます。私は要求
とリフレッシュトークンの有効期限が切れている、\方法が打撃を受ける上記のクラスのNONEを作る際にここで、私は再び
public class SmartCardOAuthAuthenticationTokenProvider : IAuthenticationTokenProvider
{
private IDataAccessFactoryFactory _producesFactoryThatProducesIAuthenticateDataAccess;
public SmartCardOAuthAuthenticationTokenProvider(IDataAccessFactoryFactory producesFactoryThatProducesIAuthenticateDataAccess)
{
_producesFactoryThatProducesIAuthenticateDataAccess = producesFactoryThatProducesIAuthenticateDataAccess;
}
public async Task CreateAsync(AuthenticationTokenCreateContext context)
{
var clientid = context.Ticket.Properties.Dictionary["as:client_id"];
if (string.IsNullOrEmpty(clientid))
{
return;
}
var refreshTokenId = Guid.NewGuid().ToString("n");
using(IDataAccessFactory producesIAuthenticateDataAccess = _producesFactoryThatProducesIAuthenticateDataAccess.GetDataAccessFactory())//using (IAuthorizationDataAccess _repo = new AuthRepository())
{
IAuthorizationDataAccess _repo = producesIAuthenticateDataAccess.GetDataAccess<IAuthorizationDataAccess>();
var refreshTokenLifeTime = context.OwinContext.Get<string>("as:clientRefreshTokenLifeTime");
var token = new RefreshToken()
{
RefreshTokenId = Helper.GetHash(refreshTokenId),
ClientId = clientid,
Subject = context.Ticket.Identity.Name,
IssuedUtc = DateTime.UtcNow,
ExpiresUtc = DateTime.UtcNow.AddMinutes(Convert.ToDouble(refreshTokenLifeTime))
};
context.Ticket.Properties.IssuedUtc = token.IssuedUtc;
context.Ticket.Properties.ExpiresUtc = token.ExpiresUtc;
token.ProtectedTicket = context.SerializeTicket();
var result = await _repo.AddRefreshTokenAsync(token);
if (result)
{
context.SetToken(refreshTokenId);
}
}
}
public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
{
var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin");
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });
string hashedTokenId = Helper.GetHash(context.Token);
//using (IAuthorizationDataAccess _repo = new AuthRepository())
//{
using (IDataAccessFactory producesIAuthenticateDataAccess = _producesFactoryThatProducesIAuthenticateDataAccess.GetDataAccessFactory()) //using (AuthRepository _repo = new AuthRepository())
{
IAuthorizationDataAccess _repo = producesIAuthenticateDataAccess.GetDataAccess<IAuthorizationDataAccess>();
var refreshToken = await _repo.FindRefreshTokenAsync(hashedTokenId);
if (refreshToken != null)
{
//Get protectedTicket from refreshToken class
context.DeserializeTicket(refreshToken.ProtectedTicket);
var result = await _repo.RemoveRefreshTokenAsync(hashedTokenId);
}
}
}
public void Create(AuthenticationTokenCreateContext context)
{
throw new NotImplementedException();
}
public void Receive(AuthenticationTokenReceiveContext context)
{
throw new NotImplementedException();
}
}
public class SmartCardOAuthAuthorizationProvider : OAuthAuthorizationServerProvider
{
private IDataAccessFactoryFactory _producesFactoryThatProducesIAuthenticateDataAccess;
public SmartCardOAuthAuthorizationProvider(IDataAccessFactoryFactory producesFactoryThatProducesIAuthenticateDataAccess)
{
_producesFactoryThatProducesIAuthenticateDataAccess = producesFactoryThatProducesIAuthenticateDataAccess;
}
public override System.Threading.Tasks.Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin");
if (allowedOrigin == null) allowedOrigin = "*";
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });
if (context.UserName != "onlyOneHardCodedUserForSakeOfExploration" && context.Password!="thePassword")
{
context.SetError("invalid_grant", "the user name or password is incorrect");
return Task.FromResult<object>(null); ;
}
ClaimsIdentity identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim(ClaimTypes.Role, "PostVSDebugBreakModeEnterEventArgs"));
identity.AddClaim(new Claim(DatawareClaimTypes.SmartCardUserId.ToString(), 1.ToString()));
var props = new AuthenticationProperties(new Dictionary<string, string>
{
{
"as:client_id", (context.ClientId == null) ? string.Empty : context.ClientId
},
{
"userName", context.UserName
}
});
var ticket = new AuthenticationTicket(identity, props);
//ticket.Properties.ExpiresUtc = new DateTimeOffset(DateTime.Now.AddDays(2));
context.Validated(ticket);
return Task.FromResult<object>(null);
}
public override System.Threading.Tasks.Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
string clientId = string.Empty;
string clientSecret = string.Empty;
Client client = null;
if (!context.TryGetBasicCredentials(out clientId, out clientSecret))
{
context.TryGetFormCredentials(out clientId, out clientSecret);
}
if (context.ClientId == null)
{
//Remove the comments from the below line context.SetError, and invalidate context
//if you want to force sending clientId/secrects once obtain access tokens.
//context.Validated();
context.SetError("invalid_clientId", "ClientId should be sent.");
return Task.FromResult<object>(null);
}
string[] clientIdClientUnique = context.ClientId.Split(':');
if (clientIdClientUnique == null || clientIdClientUnique.Length <= 1)
{
context.SetError("invalid_client_unique");
return Task.FromResult<object>(null);
}
clientId = clientIdClientUnique[0];
string clientUnique = clientIdClientUnique[1];
using (IDataAccessFactory producesIAuthenticateDataAccess = _producesFactoryThatProducesIAuthenticateDataAccess.GetDataAccessFactory()) //using (AuthRepository _repo = new AuthRepository())
{
IAuthorizationDataAccess _repo = producesIAuthenticateDataAccess.GetDataAccess<IAuthorizationDataAccess>();
client = _repo.FindClient(clientId);//new Client { Active = true, AllowedOrigin = "*", ApplicationType = ApplicationTypes.DesktopClient, ClientId = context.ClientId, Name = "Visual Studio Event Source", RefreshTokenLifeTimeInMinutes = 14400, Secret = Helper.GetHash(clientSecret) };//_repo.FindClient(context.ClientId);
}
if (client == null)
{
//context.SetError("invalid_client_unique");
context.SetError("invalid_clientId", string.Format("Client '{0}' is not registered in the system.", context.ClientId));
return Task.FromResult<object>(null);
}
if (string.IsNullOrWhiteSpace(clientSecret))
{
context.SetError("invalid_clientId", "Client secret should be sent.");
return Task.FromResult<object>(null);
}
else
{
if (client.Secret != Helper.GetHash(clientSecret))
{
context.SetError("invalid_clientId", "Client secret is invalid.");
return Task.FromResult<object>(null);
}
}
if (!client.Active)
{
context.SetError("invalid_clientId", "Client is inactive.");
return Task.FromResult<object>(null);
}
context.OwinContext.Set<string>("as:clientAllowedOrigin", client.AllowedOrigin);
context.OwinContext.Set<string>("as:clientRefreshTokenLifeTime", client.RefreshTokenLifeTimeInMinutes.ToString());
context.Validated();
return Task.FromResult<object>(null);
}
public override Task GrantRefreshToken(OAuthGrantRefreshTokenContext context)
{
var originalClient = context.Ticket.Properties.Dictionary["as:client_id"];
var currentClient = context.ClientId;
if (originalClient != currentClient)
{
context.SetError("invalid_clientId", "Refresh token is issued to a different clientId.");
return Task.FromResult<object>(null);
}
// Change auth ticket for refresh token requests
var newIdentity = new ClaimsIdentity(context.Ticket.Identity);
newIdentity.AddClaim(new Claim("newClaim", "newValue"));
var newTicket = new AuthenticationTicket(newIdentity, context.Ticket.Properties);
context.Validated(newTicket);
return Task.FromResult<object>(null);
}
public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
{
context.AdditionalResponseParameters.Add(property.Key, property.Value);
}
return Task.FromResult<object>(null);
}
}
を持っているものです。さらに、APIに渡されたリフレッシュトークンは、SmartCardOAuthAuthenticationTokenProvider.CreateAsync
で生成したGUIDだけであり、有効期限に関する情報は含まれていません。リフレッシュによってアクセスを要求するときに上記の方法のどれもヒットしない場合、リフレッシュによって新しいアクセストークンを要求するときに何も表示されません(何も表示されません)。
私には魔法のようです。
UPDATE 1 -
public static class OwinStartUpConfig
{
public static void Configure(HttpConfiguration configFromOwinStartup)
{
configFromOwinStartup.MapHttpAttributeRoutes();
configFromOwinStartup.Routes.MapHttpRoute("Default", "{controller}/{id}", new { id = RouteParameter.Optional });
var jsonFormatter = configFromOwinStartup.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
RegiserDependencies(configFromOwinStartup);
}
public static void RegiserDependencies(HttpConfiguration configFromOwinStartup)
{
string connectionStringForSmartCardDbCntx = System.Configuration.ConfigurationManager.ConnectionStrings["SmartCardDataContext"].ConnectionString;
string projectNameWhenNewProjectCreatedDueToNoMatch = System.Configuration.ConfigurationManager.AppSettings["ProjectNameWhenNewProjectCreatedDueToNoMatch"];
Autofac.ContainerBuilder builderUsedToRegisterDependencies = new Autofac.ContainerBuilder();
builderUsedToRegisterDependencies.RegisterType<DataAccessFactoryFactoryEf>()
.As<IDataAccessFactoryFactory>()
.WithParameter(new TypedParameter(typeof(string), connectionStringForSmartCardDbCntx));
builderUsedToRegisterDependencies.Register(
c =>
new List<IProjectActivityMatch<VSDebugBreakModeEnterActivity>>
{
new MatchVSProjectWithMostRecentActivity<VSDebugBreakModeEnterActivity>(),
new MatchVSSolutionWithMostRecentActivityActivityMatch<VSDebugBreakModeEnterActivity>(),
new MatchMostRecentActivityMatch<VSDebugBreakModeEnterActivity>(),
new MatchToNewProjectActivityMatch<VSDebugBreakModeEnterActivity>(projectNameWhenNewProjectCreatedDueToNoMatch)
}
).As<IEnumerable<IProjectActivityMatch<VSDebugBreakModeEnterActivity>>>();
builderUsedToRegisterDependencies
.RegisterType<MatchDontGiveUpActivityMatch<VSDebugBreakModeEnterActivity>>()
//.WithParameter(Autofac.Core.ResolvedParameter.ForNamed<IEnumerable<IProjectActivityMatch<VSDebugBreakModeEnterActivity>>>("VSDebugBreakModeEnterActivityMatchers"))
.As<IProjectActivityMatch<VSDebugBreakModeEnterActivity>>();
builderUsedToRegisterDependencies
.RegisterType<VSDebugBreakModeEnterEventArgsEventSaver>()
.Named<ISaveVisualStudioEvents>("VSDebugBreakModeEnterSaver");
builderUsedToRegisterDependencies
.RegisterType<VSDebugBreakModeEnterEventArgsController>()
.WithParameter(Autofac.Core.ResolvedParameter.ForNamed<ISaveVisualStudioEvents>("VSDebugBreakModeEnterSaver"));
var container = builderUsedToRegisterDependencies.Build();
configFromOwinStartup.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
}
public static class OAuthStartupConfig
{
internal static void Configure(IAppBuilder app)
{
OAuthAuthorizationServerOptions oAuthServerOptions = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = false,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), //TimeSpan.FromDays(1),
Provider = new SmartCardOAuthAuthorizationProvider(new AuthorizationDataAccessFactoryFactory()),
RefreshTokenProvider = new SmartCardOAuthAuthenticationTokenProvider(new AuthorizationDataAccessFactoryFactory())
};
app.UseOAuthAuthorizationServer(oAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
UPDATEスタートアップコードを追加 - コメント
に応答して上記応答内のアクセストークンは、アクセストークンのクレーム情報及び有効期限の情報が含まれてい。これらの情報はすべて、サーバーによって上記のアクセストークンにシリアル化されます。そこで、アクセストークンの有効期限がどのようにチェックされているかを確認できます。しかし、リフレッシュトークンはどうですか?リフレッシュトークンは良いですので、リフレッシュトークンによるアクセストークンの要求が許可されていますが、リフレッシュ場合は、上記の要求に
:アクセストークンの要求は、リフレッシュトークンを使用して作るされている場合トークンが期限切れになったOAuthAuthorizationServerProviderがリフレッシュトークンの有効期限を確認する方法
繰り返しますが、私は上記のコードが実際に期限切れのリフレッシュトークンをチェックしないとリフレッシュトークンの有効期限が切れている場合、アクセストークンを許可していないことを確認しているが、それはどのように知っているのですか?私はOAuthAuthorizationServerProvider派生クラスにリフレッシュトークンの有効期限をチェックするために何も書きませんでした。そう?
UPDATE
魔法はIAuthenticationTokenProvider実装のReceiveAsync方法で行われます。
public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
{
var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin");
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });
string hashedTokenId = Helper.GetHash(context.Token);
//using (IAuthorizationDataAccess _repo = new AuthRepository())
//{
using (IDataAccessFactory producesIAuthenticateDataAccess = _producesFactoryThatProducesIAuthenticateDataAccess.GetDataAccessFactory()) //using (AuthRepository _repo = new AuthRepository())
{
IAuthorizationDataAccess _repo = producesIAuthenticateDataAccess.GetDataAccess<IAuthorizationDataAccess>();
var refreshToken = await _repo.FindRefreshTokenAsync(hashedTokenId);
if (refreshToken != null)
{
//Get protectedTicket from refreshToken class
context.DeserializeTicket(refreshToken.ProtectedTicket);
var result = await _repo.RemoveRefreshTokenAsync(hashedTokenId);
}
}
}
特に、context.DeserializeTicket(refreshToken.ProtectedTicket);
という行が魔法です。それはcontext.Ticketプロパティを設定します。 ReceiveAsyncメソッドが完了したら、完了しました。手動で何かを確認する必要はありません.OWINは、チケットの有効期限が切れていることを舞台裏で知ることができます。
プロバイダをOAuthServerOptionsに接続するコードを表示できますか?サーバーオプションを作成するときにリフレッシュトークンプロバイダを指していないと思われます。 –