我想实现基于web api 2的基于声明的oauth令牌认证。为此,我已经创建OWIN承载认证失败的web api 2
[assembly: OwinStartup(typeof(PMW.Api.Startup))]
public class Startup
{
//private IUnitOfWork _unitOfWork;
//private IUserService _userService;
//private ICommonService _commonService;
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
IUnityContainer container = GetUnityContainer();
config.DependencyResolver = new UnityDependancyResolver(container);
//_unitOfWork = container.Resolve<IUnitOfWork>();
//_userService = container.Resolve<IUserService>();
//_commonService = container.Resolve<ICommonService>();
MapAutomapper();
ConfigureOAuth(app);
//var OAuthBearerOptions = new OAuthBearerAuthenticationOptions()
//{
// Provider = new QueryStringOAuthBearerProvider(),
// AccessTokenProvider = new AuthenticationTokenProvider()
// {
// OnCreate = create,
// OnReceive = receive
// },
//};
//app.UseOAuthBearerAuthentication(OAuthBearerOptions);
}
public static Action<AuthenticationTokenCreateContext> create = new Action<AuthenticationTokenCreateContext>(c =>
{
c.SetToken(c.SerializeTicket());
});
public static Action<AuthenticationTokenReceiveContext> receive = new Action<AuthenticationTokenReceiveContext>(c =>
{
c.DeserializeTicket(c.Token);
c.OwinContext.Environment["Properties"] = c.Ticket.Properties;
});
private void MapAutomapper()
{
//Mapper code
}
private IUnityContainer GetUnityContainer()
{
//Create UnityContainer
IUnityContainer container = //unity mapping
return container;
}
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider()
};
// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
和授权类被定义为下面
public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
IUnityContainer container = //unity code for mapping login related service
var _commonService=container.Resolve<ICommonService>() ;
var password =// Encrypt password
UserService _userService = new UserService(container.Resolve<IUnitOfWork>(),
container.Resolve<IUserMasterRepository>(), container.Resolve<IUserDetailRepository>());
var userToPass = new UserDTO()
{
EmailId = context.UserName,
Password = password
};
var user = _userService.AuthenticateUser(userToPass);
if (!user.Succeeded)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
identity.AddClaim(new Claim(ClaimTypes.Role, "user"));
context.Validated(identity);
}
}
该代码被适当地工作,并产生令牌的客户端应用程序。但是,如果我使用Authrize属性如下所示。它总是失败,错误401未经授权。
[Authorize]
[HttpGet]
public UserDTO Test()
{
return new UserDTO();
}
以下是请求和失败方法详细信息的快照。
请让我们知道我缺少什么才能正确实施授权流程。
你能说明你如何从测试方法中获取GET?我的意思是,正在发送:授权:承载者作为请求标头正确吗? –
2014-12-02 16:24:35
我已经添加了包含授权承载令牌的请求部分引用的快照。 – parth1729 2014-12-03 09:03:00
从快照中的信息看来,您似乎有两个项目:一个用于授权,另一个用于资源。你有没有在两个webconfig文件中检查machinekey是否相同?检查这个问题:http://stackoverflow.com/questions/25901414/owin-authentication-between-mvc-5-and-web-api-separate-iis-applications/25942811#25942811 – 2014-12-03 10:16:13