C# 如何在asp.net web api中自定义oAuth令牌提供程序
我想改变默认的承载令牌系统的工作方式 我想登录到webAPI,提供设备的用户名、密码和mac地址。像这样C# 如何在asp.net web api中自定义oAuth令牌提供程序,c#,asp.net-web-api,oauth,asp.net-identity,access-token,C#,Asp.net Web Api,Oauth,Asp.net Identity,Access Token,我想改变默认的承载令牌系统的工作方式 我想登录到webAPI,提供设备的用户名、密码和mac地址。像这样 Content-Type: application/x-www-form-urlencoded username=test&password=P@ssword&grant_type=password&client_id=android&device_info=MAC_Address 然后我希望API为我提供一个刷新令牌。此令牌的有效期为7天,并允许我
Content-Type: application/x-www-form-urlencoded
username=test&password=P@ssword&grant_type=password&client_id=android&device_info=MAC_Address
然后我希望API为我提供一个刷新令牌。此令牌的有效期为7天,并允许我获取新的访问令牌。但是,在刷新令牌中,我希望在令牌中保存/嵌入用户密码的安全戳以及删除日期。这样,当请求新的访问令牌时,我可以检查安全戳。(解决密码更改方案)
我的访问令牌只需要存储少量信息就可以工作。我不要求访问令牌存储任何特定的内容。我希望它尽可能小。当它过期时,我将使用我的刷新令牌请求一个新的访问令牌
现在我已经试着去实现上面的内容,但是我自己对在哪里实现什么感到非常困惑。这是我得到的
步骤1:Startup.Auth.cs
//Configure the application for OAuth based flow
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/Token"),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
Provider = new SimpleAuthorizationServerProvider(),
RefreshTokenProvider = new SimpleRefreshTokenProvider(),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(20)
};
现在在这里我已经有一些问题了。我想要两个提供者,一个处理刷新令牌
,另一个处理访问令牌
。我需要设置哪些提供者?因为我看到还有一个叫做AccessTokenProvider=
那么Provider=
是做什么的
步骤2:重新设置TokenProvider。这就是我到目前为止所做的:
public class SimpleRefreshTokenProvider : IAuthenticationTokenProvider
{
//Used to store all the refresh tokens
public static ConcurrentDictionary<string, AuthenticationTicket> RefreshTokens = new ConcurrentDictionary<string, AuthenticationTicket>();
public Task CreateAsync(AuthenticationTokenCreateContext context)
{
var guid = Guid.NewGuid().ToString("N");
//copy properties and set the desired lifetime of refresh token
var refreshTokenProperties = new AuthenticationProperties(context.Ticket.Properties.Dictionary)
{
IssuedUtc = context.Ticket.Properties.IssuedUtc,
ExpiresUtc = DateTime.UtcNow.AddDays(7)
};
//TODO: get mac address from the request headers??
//TODO: save the mac address to db along with user and date
var refreshTokenTicket = new AuthenticationTicket(context.Ticket.Identity, refreshTokenProperties);
RefreshTokens.TryAdd(guid, refreshTokenTicket);
context.SetToken(guid);
return Task.FromResult<object>(null);
}
public Task ReceiveAsync(AuthenticationTokenReceiveContext context)
{
AuthenticationTicket ticket;
if (RefreshTokens.TryRemove(context.Token, out ticket))
{
context.SetTicket(ticket);
}
return Task.FromResult<object>(null);
}
public void Receive(AuthenticationTokenReceiveContext context)
{
throw new NotImplementedException();
}
public void Create(AuthenticationTokenCreateContext context)
{
throw new NotImplementedException();
}
}
公共类SimpleRefreshTokenProvider:IAAuthenticationTokenProvider
{
//用于存储所有刷新令牌
公共静态ConcurrentDictionary RefreshTokens=新ConcurrentDictionary();
公共任务CreateSync(AuthenticationTokenCreateContext上下文)
{
var guid=guid.NewGuid().ToString(“N”);
//复制属性并设置刷新令牌的所需生存期
var refreshttokenproperties=newauthenticationproperties(context.Ticket.Properties.Dictionary)
{
IssuedUtc=context.Ticket.Properties.IssuedUtc,
ExpiresUtc=DateTime.UtcNow.AddDays(7)
};
//TODO:从请求头获取mac地址??
//TODO:将mac地址与用户和日期一起保存到db
var refreshttokenticket=newauthenticationticket(context.Ticket.Identity,refreshttokenproperties);
RefreshTokens.TryAdd(guid,refreshTokenTicket);
SetToken(guid);
返回Task.FromResult(空);
}
公共任务ReceiveAsync(AuthenticationTokenReceiveContext上下文)
{
认证票证;
if(refreshtokes.TryRemove(context.Token,out ticket))
{
上下文。设置票证(票证);
}
返回Task.FromResult(空);
}
public void Receive(AuthenticationTokenReceiveContext上下文)
{
抛出新的NotImplementedException();
}
公共void创建(AuthenticationTokenCreateContext上下文)
{
抛出新的NotImplementedException();
}
}
如果我理解正确的话。SimpleRefreshTokenProvider的目的是建立一个RefreshToken,并在api接收到一个包含RefreshToken的请求时验证它
步骤3:SimpleAuthorizationServerProvider。这就是我目前所拥有的。但我有一种感觉,这就是我出错的地方。或者我感到困惑,这门课的目的是什么?是否不验证AccessToken
public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
// Not concerned about clients yet
context.Validated();
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
// validate user credentials
var userManager = context.OwinContext.GetUserManager<FskUserManager>();
FskUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
// create identity
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
OAuthDefaults.AuthenticationType);
ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager,
CookieAuthenticationDefaults.AuthenticationType);
//Set properties of the token
// create metadata to pass on to refresh token provider
AuthenticationProperties properties = new AuthenticationProperties(new Dictionary<string, string>
{
{"userName", user.UserName}
});
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(cookiesIdentity);
}
public override async Task GrantRefreshToken(OAuthGrantRefreshTokenContext context)
{
string originalClient;
context.Ticket.Properties.Dictionary.TryGetValue("as:client_id", out originalClient);
var currentClient = context.ClientId;
// chance to change authentication ticket for refresh token requests
var newId = new ClaimsIdentity(context.Ticket.Identity);
newId.AddClaim(new Claim("newClaim", "refreshToken"));
var newTicket = new AuthenticationTicket(newId, context.Ticket.Properties);
context.Validated(newTicket);
}
}
公共类SimpleAuthorizationServerProvider:OAuthAuthorizationServerProvider
{
公共重写异步任务ValidateClientAuthentication(OAuthValidateClientAuthenticationContext)
{
//还不关心客户吗
context.Validated();
}
公共重写异步任务GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentials上下文)
{
//验证用户凭据
var userManager=context.OwinContext.GetUserManager();
FskUser user=await userManager.FindAsync(context.UserName,context.Password);
if(user==null)
{
SetError(“无效的授权”,“用户名或密码不正确”);
回来
}
//创造身份
ClaimsIdentity oAuthIdentity=等待用户.GenerateUserIdentityAsync(userManager,
OAuthDefaults.AuthenticationType);
ClaimSideEntity cookiesIdentity=等待用户.GenerateUserIdentity异步(userManager,
CookieAuthenticationDefaults.AuthenticationType);
//设置令牌的属性
//创建要传递给刷新令牌提供程序的元数据
AuthenticationProperties=新的AuthenticationProperties(新字典
{
{“userName”,user.userName}
});
AuthenticationTicket=新的AuthenticationTicket(OAuthidentitity,属性);
上下文。已验证(票证);
context.Request.context.Authentication.sign(cookiesIdentity);
}
公共重写异步任务GrantRefreshToken(OAuthGrantRefreshTokenContext)
{
字符串原始客户端;
context.Ticket.Properties.Dictionary.TryGetValue(“as:client_id”,out originalClient);
var currentClient=context.ClientId;
//更改刷新令牌请求的身份验证票证的机会
var newId=newclaimsidentity(context.Ticket.Identity);
newId.AddClaim(新索赔(“新索赔”、“刷新令牌”));
var newTicket=new