之前已经简单实现了OAUTH2的授权码模式(Authorization Code),但是基于JAVA的,今天花了点时间调试了OWIN的实现,基本就把基于OWIN的OAUHT2的四种模式实现完了。官方推荐的.NET 包有

Katana已经不更新了,新的版本是已经是asp.net core 1.0的一部分,实现OAUTH2好的选择可以考虑使用新版或IdentityServer3对应asp.net core 1.0版本为IdentityServer4。

Startup

public partial class Startup
{
private readonly ConcurrentDictionary<string, string> _authenticationCodes = new ConcurrentDictionary<string, string>(StringComparer.Ordinal);
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = Paths.AuthenticationType,
AuthenticationMode = AuthenticationMode.Passive,
LoginPath = new PathString(Paths.LoginPath),
LogoutPath = new PathString(Paths.LogoutPath),
}); app.UseOAuthBearerTokens(new OAuthAuthorizationServerOptions
{
AuthorizeEndpointPath = new PathString(Paths.AuthorizePath),
TokenEndpointPath = new PathString(Paths.TokenPath),
AccessTokenExpireTimeSpan = TimeSpan.FromHours(2),
Provider = new OAuthAuthorizationServerProvider
{
OnValidateClientRedirectUri = ValidateClientRedirectUri,
OnValidateClientAuthentication = ValidateClientAuthentication,
OnGrantResourceOwnerCredentials = GrantResourceOwnerCredentials,
OnGrantClientCredentials = GrantClientCredetails
},
//Provider = new ApplicationOAuthProvider(),
AuthorizationCodeProvider = new AuthenticationTokenProvider
{
OnCreate = CreateAuthenticationCode,
OnReceive = ReceiveAuthenticationCode,
},
RefreshTokenProvider = new AuthenticationTokenProvider
{
OnCreate = CreateRefreshToken,
OnReceive = ReceiveRefreshToken,
},
ApplicationCanDisplayErrors = true,
#if DEBUG
//HTTPS is allowed only AllowInsecureHttp = false
AllowInsecureHttp = true,
#endif
});
} private void CreateAuthenticationCode(AuthenticationTokenCreateContext context)
{
context.SetToken(Guid.NewGuid().ToString("n") + Guid.NewGuid().ToString("n"));
_authenticationCodes[context.Token] = context.SerializeTicket();
} private void ReceiveAuthenticationCode(AuthenticationTokenReceiveContext context)
{
string value;
if (_authenticationCodes.TryRemove(context.Token, out value))
{
context.DeserializeTicket(value);
}
} private Task GrantClientCredetails(OAuthGrantClientCredentialsContext context)
{
var identity = new ClaimsIdentity(new GenericIdentity(context.ClientId, OAuthDefaults.AuthenticationType), context.Scope.Select(x => new Claim("urn:oauth:scope", x)));
context.Validated(identity);
return Task.FromResult(0);
} private Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var identity = new ClaimsIdentity(new GenericIdentity(context.UserName, OAuthDefaults.AuthenticationType), context.Scope.Select(x => new Claim("urn:oauth:scope", x)));
context.Validated(identity);
return Task.FromResult(0);
} private Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
string clientId;
string clientSecret;
if (context.TryGetBasicCredentials(out clientId, out clientSecret) || context.TryGetFormCredentials(out clientId, out clientSecret))
{
context.Validated();
}
return Task.FromResult(0);
} private Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
{
if (context.ClientId == Clients.Client1.Id)
{
context.Validated();
//context.Validated(Clients.Client1.RedirectUrl);
}
else if (context.ClientId == Clients.Client2.Id)
{
context.Validated(Clients.Client2.RedirectUrl);
}
return Task.FromResult(0);
} private void CreateRefreshToken(AuthenticationTokenCreateContext context)
{
context.SetToken(context.SerializeTicket());
} private void ReceiveRefreshToken(AuthenticationTokenReceiveContext context)
{
context.DeserializeTicket(context.Token);
}
}

OAuthController

/// <summary>
/// 授权码模式授权
/// </summary>
/// <returns></returns>
public ActionResult Authorize()
{
var authentication = HttpContext.GetOwinContext().Authentication;
var ticket = authentication.AuthenticateAsync(Paths.AuthenticationType).Result;
var identity = ticket != null ? ticket.Identity : null;
if (identity == null)
{
authentication.Challenge(Paths.AuthenticationType);
return new HttpUnauthorizedResult();
}
var scopes = (Request.QueryString.Get("scope") ?? "").Split(' ');
if (Request.HttpMethod == "POST")
{
if (!string.IsNullOrEmpty(Request.Form.Get("submit.Grant")))
{
identity = new ClaimsIdentity(identity.Claims, "Bearer", identity.NameClaimType, identity.RoleClaimType);
foreach (var scope in scopes)
{
identity.AddClaim(new Claim("urn:oauth:scope", scope));
}
authentication.SignIn(identity);
}
if (!string.IsNullOrEmpty(Request.Form.Get("submit.Login")))
{
authentication.SignOut("Application");
authentication.Challenge("Application");
return new HttpUnauthorizedResult();
}
}
return View();
}

AccountController

/// <summary>
/// 用户登录
/// </summary>
/// <returns></returns>
public ActionResult Login()
{
var authentication = HttpContext.GetOwinContext().Authentication;
if (Request.HttpMethod == "POST")
{
var isPersistent = !string.IsNullOrEmpty(Request.Form.Get("isPersistent"));
if (!string.IsNullOrEmpty(Request.Form.Get("submit.Signin")))
{
authentication.SignIn(
new AuthenticationProperties { IsPersistent = isPersistent },
new ClaimsIdentity(new[] { new Claim(ClaimsIdentity.DefaultNameClaimType, Request.Form["username"]) }, "Application"));
}
}
return View();
} /// <summary>
/// 退出
/// </summary>
/// <returns></returns>
public ActionResult Logout()
{
return View();
}

调试

获得授权码

GET /oauth/authorize?client_id=irving&redirect_uri=http://localhost:38500/oauth_callback&state=LYUVwcuaGuKeRTjxhdFzhQ&scope=bio

%20notes&response_type=code HTTP/1.1

http://localhost:56889/oauth/authorize?

client_id=irving&redirect_uri=http://localhost:38500/oauth_callback&state=LYUVwcuaGuKeRTjxhdFzhQ&scope=bio%20notes&response_type=code

页面重定向

HTTP/1.1 302 Found

Location: /oauth_callback?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz

http://localhost:56889/oauth_callback?code=0aa3e35bd515413bb93bdb6fb015591cc763a8d30c554730a07ebd39e3149252&state=LYUVwcuaGuKeRTjxhdFzhQ

获得令牌

POST /token HTTP/1.1

Host: server.example.com

Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=929dc42905a24e79bdf028f7043769acddd90056ca8141708b3834ec174e8083&state=LYUVwcuaGuKeRTjxhdFzhQ&redirect_uri=http://localhost:38500/oauth_callback

源码:https://github.com/zhouyongtao/SecuringForWebAPI/tree/master/KatanaForWebAPI

注意事项

资源服务器识别认证服务器颁发的令牌, 需要配置相同的machinekey

<machineKey decryptionKey="B7EFF1C5839A624E3F97D0268917EDE82F408D2ECBFAC817" validation="SHA1" validationKey="C2B8DF31AB9624D69428066DFDA1A479542825F3B48865C4E47AF6A026F22D853DEC2B3248DF268599BF89EF78B9E86CA05AC73577E0D5A14C45E0267588850B" />

REFER:

http://beginor.github.io/2015/01/24/oauth2-server-with-owin.html

http://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server

基于OWIN WebAPI 使用OAUTH2授权服务【授权码模式(Authorization Code)】的更多相关文章

  1. 【干货】基于Owin WebApi 使用OAuth2进行客户端授权服务

    前言:采用Client Credentials方式,即密钥key/password,场景一般是分为客户端限制必须有权限才能使用的模块,这和微信公众号开放平台很类似. 让用户通过客户端去获取自己的tok ...

  2. IdentityServer4 (3) 授权码模式(Authorization Code)

    写在前面 1.源码(.Net Core 2.2) git地址:https://github.com/yizhaoxian/CoreIdentityServer4Demo.git 2.相关章节 2.1. ...

  3. Apache Oltu 实现 OAuth2.0 服务端【授权码模式(Authorization Code)】

    要实现OAuth服务端,就得先理解客户端的调用流程,服务提供商实现可能也有些区别,实现OAuth服务端的方式很多,具体可能看 http://oauth.net/code/ 各语言的实现有(我使用了Ap ...

  4. Owin中间件搭建OAuth2.0认证授权服务体会

    继两篇转载的Owin搭建OAuth 2.0的文章,使用Owin中间件搭建OAuth2.0认证授权服务器和理解OAuth 2.0之后,我想把最近整理的资料做一下总结. 前两篇主要是介绍概念和一个基本的D ...

  5. 使用Owin中间件搭建OAuth2.0认证授权服务器

    前言 这里主要总结下本人最近半个月关于搭建OAuth2.0服务器工作的经验.至于为何需要OAuth2.0.为何是Owin.什么是Owin等问题,不再赘述.我假定读者是使用Asp.Net,并需要搭建OA ...

  6. 基于 IdentityServer3 实现 OAuth 2.0 授权服务【密码模式(Resource Owner Password Credentials)】

    密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码.客户端使用这些信息,向"服务商提供商"索要授权 ...

  7. 【PHP】基于ThinkPHP框架搭建OAuth2.0服务

    [PHP]基于ThinkPHP框架搭建OAuth2.0服务 http://leyteris.iteye.com/blog/1483403

  8. OAuth2.0学习(1-6)授权方式3-密码模式(Resource Owner Password Credentials Grant)

    授权方式3-密码模式(Resource Owner Password Credentials Grant) 密码模式(Resource Owner Password Credentials Grant ...

  9. OAuth 第三方登录授权码(authorization code)方式的小例子

    假如上面的网站A,可以通过GitHub账号登录: 下面以OAuth其中一种方式,授权码(authorization code)方式为例. 一.第三方登录的原理 所谓第三方登录,实质就是 OAuth 授 ...

随机推荐

  1. cin判断读取结束 C++语言

    cin是C++的输入流,可以通过>>进行读取. 判断读取结束,一般有两种方法,具体取决于与输入的约定. 1 以特殊值结尾. 如输入整数,以-1结束,那么当读到-1的时候,就确定读取结束了. ...

  2. python学习笔记:文件操作和集合(转)

    转自:http://www.nnzhp.cn/article/16/ 这篇博客来说一下python对文件的操作. 对文件的操作分三步: 1.打开文件获取文件的句柄,句柄就理解为这个文件 2.通过文件句 ...

  3. ---Arch Linux 之AUR

    只需下载压缩包,解压,进入文件夹,里面好像也只有一个PKBUILD文件,makepkg -s (自动下载程序然后编译打包), 然后pacman -U xxxx.pkg.xz 就好了

  4. angularjs 延迟更新和angularjsUI

    angularjsUI库https://material.angularjs.org/latest/ ng-model-options="{ updateOn: 'blur' }" ...

  5. asp.net前台绑定时间格式时,定义时间格式

    <%#Eval("news_time","{0:yyyy-MM-dd}") %><%#((DateTime)Eval("news_t ...

  6. Java设计模式——装饰者模式

    JAVA 设计模式 装饰者模式 用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式 ...

  7. 平行四边形TikZ作图

    %!TEX program = pdflatex \documentclass[varwidth=true, border=2pt]{standalone} \usepackage{tikz} \us ...

  8. Python—元组tuple

    列表的知识其实就类似于c语言中的数组,可插入.修改.list=[a,b,c,d] 而元组tuple,一旦初始化即不可修改.好处与绝对安全. 定义一个空的元组:t=() 定义只有一个元素的元组:t=(1 ...

  9. Azure DW

    1. 安装环境a. 安装环境https://www.microsoft.com/web/downloads/platform.aspx b. InputImport-Module 'C:\Progra ...

  10. Linux系统编程-setitimer函数

    功能:linux系统编程中,setitimer是一个经常被使用的函数,可用来实现延时和定时的功能. 头文件:sys/time.h 函数原型: int setitimer(int which, cons ...