OWIN OAuth 2.0 Authorization Server

OWIN OAuth 2.0 Authorization Server

源码在上面的地址中可以下载

打开客户端页面http://localhost:38500/

客户端代码引用了DotNetOpenAuth.OAuth2

public class HomeController : Controller
    {
        private WebServerClient _webServerClient;

        public ActionResult Index()
        {
            ViewBag.AccessToken = Request.Form["AccessToken"] ?? "";
            ViewBag.RefreshToken = Request.Form["RefreshToken"] ?? "";
            ViewBag.Action = "";
            ViewBag.ApiResponse = "";

            InitializeWebServerClient();
            var accessToken = Request.Form["AccessToken"];
            if (string.IsNullOrEmpty(accessToken))
            {
                var authorizationState = _webServerClient.ProcessUserAuthorization(Request);
                if (authorizationState != null)
                {
                    ViewBag.AccessToken = authorizationState.AccessToken;
                    ViewBag.RefreshToken = authorizationState.RefreshToken;
                    ViewBag.Action = Request.Path;
                }
            }

            if (!string.IsNullOrEmpty(Request.Form.Get("submit.Authorize")))
            {
                var userAuthorization = _webServerClient.PrepareRequestUserAuthorization(new[] { "bio", "notes" });
                userAuthorization.Send(HttpContext);
                Response.End();
            }
            else if (!string.IsNullOrEmpty(Request.Form.Get("submit.Refresh")))
            {
                var state = new AuthorizationState
                {
                    AccessToken = Request.Form["AccessToken"],
                    RefreshToken = Request.Form["RefreshToken"]
                };
                if (_webServerClient.RefreshAuthorization(state))
                {
                    ViewBag.AccessToken = state.AccessToken;
                    ViewBag.RefreshToken = state.RefreshToken;
                }
            }
            else if (!string.IsNullOrEmpty(Request.Form.Get("submit.CallApi")))
            {
                var resourceServerUri = new Uri(Paths.ResourceServerBaseAddress);
                var client = new HttpClient(_webServerClient.CreateAuthorizingHandler(accessToken));
                var body = client.GetStringAsync(new Uri(resourceServerUri, Paths.MePath)).Result;
                ViewBag.ApiResponse = body;
            }

            return View();
        }

        private void InitializeWebServerClient()
        {
            var authorizationServerUri = new Uri(Paths.AuthorizationServerBaseAddress);
            var authorizationServer = new AuthorizationServerDescription
            {
                AuthorizationEndpoint = new Uri(authorizationServerUri, Paths.AuthorizePath),
                TokenEndpoint = new Uri(authorizationServerUri, Paths.TokenPath)
            };
            _webServerClient = new WebServerClient(authorizationServer, Clients.Client1.Id, Clients.Client1.Secret);
        }
    }

2.点击Authorize按钮,在客户端添加两个Scope

var userAuthorization = _webServerClient.PrepareRequestUserAuthorization(new[] { "bio", "notes" });

调用如下

public OutgoingWebResponse PrepareRequestUserAuthorization(IEnumerable<string> scopes = null, Uri returnTo = null);

此时会到服务端进行客户验证

private Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
        {
            if (context.ClientId == Clients.Client1.Id)
            {
                context.Validated(Clients.Client1.RedirectUrl);
            }
            else if (context.ClientId == Clients.Client2.Id)
            {
                context.Validated(Clients.Client2.RedirectUrl);
            }
            return Task.FromResult(0);
        }

验证后跳转到Authorize,首先判断是否登陆

var authentication = HttpContext.GetOwinContext().Authentication;
            var ticket = authentication.AuthenticateAsync("Application").Result;
            var identity = ticket != null ? ticket.Identity : null;
            if (identity == null)
            {
                authentication.Challenge("Application");
                return new HttpUnauthorizedResult();
            }

没有登陆的话跳转到Login页面

http://localhost:11625/Account/Login?ReturnUrl=%2FOAuth%2FAuthorize%3Fclient_id%3D123456%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A38500%252F%26state%3D4PH8wxITy6KAVSpnt4YpAA%26scope%3Dbio%2520notes%26response_type%3Dcode

使用UrlDecode可以看得更明白

http://localhost:11625/Account/Login?ReturnUrl=/OAuth/Authorize?client_id=123456&redirect_uri=http%3A%2F%2Flocalhost%3A38500%2F&state=4PH8wxITy6KAVSpnt4YpAA&scope=bio%20notes&response_type=code

再次解码

http://localhost:11625/Account/Login?ReturnUrl=/OAuth/Authorize?client_id=123456&redirect_uri=http://localhost:38500/&state=4PH8wxITy6KAVSpnt4YpAA&scope=bio notes&response_type=code

这里随便输入一个用户名123456,点击Sign In按钮

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();
        }

会通过OWIN写入身份,再次到服务端进行验证

验证后进行授权确认

http://localhost:11625/OAuth/Authorize?client_id=123456&redirect_uri=http%3A%2F%2Flocalhost%3A38500%2F&state=4PH8wxITy6KAVSpnt4YpAA&scope=bio%20notes&response_type=code

解码后

http://localhost:11625/OAuth/Authorize?client_id=123456&redirect_uri=http://localhost:38500/&state=4PH8wxITy6KAVSpnt4YpAA&scope=bio notes&response_type=code

点击Grant按钮,同样会先进行验证,然后写入Scope,注意这里写入的Bearer,在后面的资源服务器验证时使用

通过登陆后会生成token

private void CreateAuthenticationCode(AuthenticationTokenCreateContext context)
        {
            context.SetToken(Guid.NewGuid().ToString("n") + Guid.NewGuid().ToString("n"));
            _authenticationCodes[context.Token] = context.SerializeTicket();
        }

返回到客户端,请求token

服务端先验证授权

private Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            string clientId;
            string clientSecret;
            if (context.TryGetBasicCredentials(out clientId, out clientSecret) ||
                context.TryGetFormCredentials(out clientId, out clientSecret))
            {
                if (clientId == Clients.Client1.Id && clientSecret == Clients.Client1.Secret)
                {
                    context.Validated();
                }
                else if (clientId == Clients.Client2.Id && clientSecret == Clients.Client2.Secret)
                {
                    context.Validated();
                }
            }
            return Task.FromResult(0);
        }

然后移除前面生成的Code

private void ReceiveAuthenticationCode(AuthenticationTokenReceiveContext context)
        {
            string value;
            if (_authenticationCodes.TryRemove(context.Token, out value))
            {
                context.DeserializeTicket(value);
            }
        }

再生成RefreshToken

回到客户端

页面

http://localhost:38500/?code=cd086e2e868e4899ac8a15c332036cd4e52f344dee804351a0789eb20bb1ead5&state=m54g6dYyfMUfYNf7F9Qbcw

点击Refresh按钮

会重新到服务器先做授权验证ValidateClientAuthentication,验证成功后重新生成token

点击访问受保护资源API,因为受保护资源同样是使用OWIN验证的

using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(ResourceServer.Startup))]

namespace ResourceServer
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
        }
    }
}
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ResourceServer
{
    public partial class Startup
    {
        public void ConfigureAuth(IAppBuilder app)
        {
            app.UseOAuthBearerAuthentication(new Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationOptions());
        }
    }
}
namespace ResourceServer.Controllers
{
    [Authorize]
    public class MeController : ApiController
    {
        public string Get()
        {
            return this.User.Identity.Name;
        }
    }
}

结果如下

这里从授权Server到资源Server都是使用OWIN,关键就在这两个项目中有相同的配置

<system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
    <machineKey decryptionKey="B7EFF1C5839A624E3F97D0268917EDE82F408D2ECBFAC817" validation="SHA1" validationKey="C2B8DF31AB9624D69428066DFDA1A479542825F3B48865C4E47AF6A026F22D853DEC2B3248DF268599BF89EF78B9E86CA05AC73577E0D5A14C45E0267588850B" />
  </system.web>
时间: 2024-10-24 04:19:41

OWIN OAuth 2.0 Authorization Server的相关文章

The OAuth 2.0 Authorization Framework-摘自https://tools.ietf.org/html/rfc6749

Internet Engineering Task Force (IETF) D. Hardt, Ed. Request for Comments: 6749 Microsoft Obsoletes: 5849 October 2012 Category: Standards Track ISSN: 2070-1721 The OAuth 2.0 Authorization Framework Abstract The OAuth 2.0 authorization framework enab

【rfc6749】机翻 The OAuth 2.0 Authorization Framework

本文禁止转载 原文地址  http://tools.ietf.org/html/rfc6749 下面内容全部是谷歌娘的翻译 = = ,写这个的目的是给自己留个备份,这样就不用每次打开谷歌娘了. ------------------------- 机翻的分割线 ---------------------------------------- OAuth的2.0授权框架 抽象 OAuth的2.0授权框架允许第三方 应用程序获取有限的访问HTTP服务,无论是在 代表的资源所有者通过编排批准互动 资源所

【7】.net WebAPI Owin OAuth 2.0 密码模式验证实例

1.OAuth密码模式 2.在VS中创建WebAPI项目 在nuget中安装: Microsoft.AspNet.WebApi.Owin Microsoft.Owin.Host.SystemWeb 这两个类库并添加Owin启动类Startup using System; using System.Threading.Tasks; using Microsoft.Owin; using Owin; using Microsoft.Owin.Security.OAuth; [assembly: Ow

ASP.NET WebApi OWIN 实现 OAuth 2.0

原文:http://www.cnblogs.com/xishuai/p/aspnet-webapi-owin-oauth2.html OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用. OAuth 允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据.每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的 2 小时内)内访问特定的资源(

OAuth 2.0 教程

OAuth 2.0 (原文:http://tutorials.jenkov.com/oauth2/index.html) OAuth 2.0 教程 OAuth 2.0 是一个开放的标准协议,允许应用程序访问其它应用的用户授权的数据.例如:一个游戏可以获取Facebook中的用户信息,或者是一个地理位置程序可以获取Foursquare的用户信息等. 这儿是一个示例图: 首先用户进入游戏的web应用,该应用要求用户通过Facebook账户登录,并定向到Facebook的登录界面,用户登录Facebo

构建微服务-使用OAuth 2.0保护API接口

微服务操作模型 基于Spring Cloud和Netflix OSS 构建微服务-Part 1 基于Spring Cloud和Netflix OSS构建微服务,Part 2 在本文中,我们将使用OAuth 2.0,创建一个的安全API,可供外部访问Part 1和Part 2完成的微服务. 关于OAuth 2.0的更多信息,可以访问介绍文档:Parecki - OAuth 2 Simplified 和 Jenkov - OAuth 2.0 Tutorial ,或者规范文档 IETF RFC 674

OAuth 2.0攻击面与案例总结

本文整理了OAuth 2.0的攻击面+实际案例+辅助测试代码. OAuth流程 本文以两种广泛使用的方案为标准展开..如对流程不了解,请先移步学习: 理解OAuth 2.0 Authorization Code response_type = code redirect_uri scope client_id state Implicit response_type = token redirect_uri scope client_id state 攻击面 CSRF导致绑定劫持 redirec

OAuth 2.0安全案例回顾

转载自:http://www.360doc.com/content/14/0311/22/834950_359713295.shtml 0x00 背景 纵观账号互通发展史,可以发现OAuth比起其它协议(如OpenID)更流行的原因是,业务双方不仅要求账号本身的认证互通(authentication:可理解为“我在双方的地盘姓甚名谁”),而是更需要双方业务流的授权打通(authorization:可理解为“我在双方的地盘上可做什么”),因为后者才能产生实际的互惠互利. 2013年将过大半,有关O

Using OAuth 2.0 for Web Server Applications, verifying a user&#39;s Android in-app subscription

在写本文之前先说些题外话. 前段时间游戏急于在GoolePlay上线,明知道如果不加Auth2.0的校验是不安全的还是暂时略过了这一步,果然没几天就发现后台记录与玩家实际付费不太一致,怀疑有玩家盗刷游戏元宝等,并且真实的走过了GooglePlay的所有支付流程完成道具兑换,时间一长严重性可想而知.经过查阅大量google官方文档后把代码补上,并在这里记录下OAuth 2.0 的使用,Google提供了OAuth2.0的好几种使用用途,每种使用方法都有些不同,具体可以看下这篇博客.在这里只写OAu