Cloud Native应用交付
  • 首页
  • 关于本站
  • 个人介绍
  • Downloads
  • Repo
    • Github
    • Container
  • F5
    • F5 Python SDK
    • F5-container
    • F5-LBaaS
  • 社交
    • 联系我
    • 微信/微博
    • 公众号
    • 打赏赞助
行至水穷处 坐看云起时
☁️We are in new App Mesh era: imesh.club ☁️
  1. 首页
  2. F5技术
  3. 正文

NGINX与oAuth2/OIDC系列三

2020年05月11日 1321点热度 1人点赞 0条评论

前面两篇(1 ,2),我们讲述了NGINX在authorization code模式下的能力,可以简单总结为NGINX既可以作为第三方应用(client)的验证代理,也可以作为Resource server角色对token进行验证或使用。在implicit模式下,NGINX能做什么呢?首先来看implicit模式的工作机制(最近太惨了,前两篇文章的画图ppt给不小心删除了,还清空了垃圾箱。。一般不没什么习惯清空垃圾箱的。。。就不重新画了,google一张图吧。。。)

在这个图里,把user想象你为,把client想象为一个浏览器然后从一个地方加载了一段纯浏览器本地运行的代码(比如react,angularJS什么的这些的纯前端实现),不需要服务器侧介入。可以看出这个过程比authorization code最大的特点就是少了server侧利用authorization code去取token的过程,授权服务器直接直接将token发给了浏览器,所以这也叫frontchannel模式,客户端是真的可以看到token的。显然在整个验证过程中,NGINX是没有什么机会介入的。因此在这种模式下,NGINX主要作为Resource Server的代理,帮助去验证相关token,并将必要的token内的信息传递后后端的服务器。

所以只要客户端浏览器将token通过合适的方式送给NGINX就可以。

Token有两种格式,一种是常见的JWT,这是一种可以offline 验证的,而且其内容是可以被直接解开的,因此对这种JWT格式的token,只需要借助NGINX的 JWT模块就可以无需验证服务器endpoint参与(NGINX上配置公开的JWK即可);另一种格式是一种私有格式,也就是非透明格式(Opaque),这种格式的token需要有验证端点来参与,这个验证过程就是所谓的token introspection(RFC7662)

在本篇实验里将基于google的JWT token方式。

Demo

图片来自nginx.com

前面的implicit模式的oAuth过程是通过goole提供的一个JS API写的,并使用了cookie.js API将客户端浏览器收到的access token转化存储到cookie里,后续浏览器带着这个Cookie来访问资源服务器(被NGINX代理)

1.准备工作,在网站的目录下放置用于客户端运行的代码以及相关的cookie.js文件

1
2
3
4
5
6
7
[root@plus1 oidc]# ll
total 12
-rw-r--r-- 1 root root 1446 May  9 14:37 index.html
-rw-r--r-- 1 root root 4772 May  9 12:28 js.cookie.js
[root@plus1 oidc]# pwd
/usr/share/nginx/html/oidc
[root@plus1 oidc]# cat index.html

html文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<html>
<head>
    <meta http-equiv="cache-control" content="no-cache" />
    <meta http-equiv="expires" content="0" />
    <title>NGINX OpenID Connect demo</title>
    <!--google的js API用于和授权服务器通信并获取返回的token-->
    <script src="https://apis.google.com/js/platform.js" async defer></script>
    <meta name="google-signin-scope" content="profile email">
    <!--这里配置你的client securit-->
    <meta name="google-signin-client_id"
          content="423878601740-s7dvt2ic*******kcmih1cq2l.apps.googleusercontent.com">
    <!--cookie js 用于实现将token写为cookie . 具体可以从这里获取https://github.com/js-cookie/js-cookie/blob/v2.1.2/src/js.cookie.js-->
    <script src="js.cookie.js"></script>
</head>
<body>
    <h2>NGINX OpenID Connect demo</h2>
    <hr/>
    <h3>Login with a Google account to get my <a href="/mysecurit/">MY SECURIT</a>.</h3>
    <table><tr><td>
    <div class="g-signin2" data-onsuccess="onSignIn" data-theme="dark"></div></td>
    <script>
      function onSignIn(googleUser) {
        var profile = googleUser.getBasicProfile();
        Cookies.set('auth_token', googleUser.getAuthResponse().id_token);
        document.getElementById('google_signout').innerHTML = '<a href="#" onclick="signOut();"><img src="' + profile.getImageUrl() + '" width=32 height=32>Sign out</a>';
      };
      function signOut() {
        var auth2 = gapi.auth2.getAuthInstance();
        auth2.signOut().then(function () {
          Cookies.remove('auth_token');
          document.getElementById('google_signout').innerHTML = '';
        });
      }
    </script>
    <td><div id="google_signout"></div></td>
    </tr></table>
    <hr/>
</body>
</html>

2.访问oidc.cnadn.net/mysecurit 请求抵达NGINX后,命中以下配置。配置使用JWT模块进行认证,客户端是通过将token放在auth_token这个Cookie传上来。这里要配置google公开的jwk文件来做验证,google JWK文件会定期轮换,所以这里需要自己额外配置cronjob定期去https://www.googleapis.com/oauth2/v3/certs 做更新。这是offline验证的缺点。 这里也可以将auth_jwt_key_file配置改为 auth_jwt_key_request https://www.googleapis.com/oauth2/v3/certs;采取线上认证。但由于环境里的NGINX机器并无不能爬梯子,所以只有用本地文件了

1
2
3
4
5
6
7
8
9
        location /mysecurit {
                auth_jwt "Google account" token=$cookie_auth_token;
                auth_jwt_key_file /etc/nginx/google_certs.jwk;
proxy_set_header x-jwt-email $jwt_claim_email;
                proxy_set_header x-jwt-name $jwt_claim_name;
                proxy_set_header x-jwt-locale $jwt_claim_locale;
                #root /usr/share/nginx/html;
                proxy_pass http://127.0.0.1:8080;
        }

3.由于首次访问不带cookie,因此jwt验证无法通过,将返回401错误,401错误将会被以下配置截获并处理。浏览器最终得到一个要求登录的提示。

1
2
3
4
5
          error_page 401 = @401;
          location @401 {
            default_type text/html;
            return 200 '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>OIDC loging redirect</title></head><body>You must <a href=/oidc/>LOGIN</a> first before pry securit!</boyd></html>';
          }

4. 用户点击登录提示里的LOGIN,页面会显示第一步中配置的html内容,由于用户尚未登录,因此google的API也无法取到用户的信息,因此提示客户最终登录GOOGLE(上述3,4两部存在两次引导登录过程,这里只是为了测试,实际可以将这个过程合并为一个)

5. 用户在Google的登录界面登录后,页面将自动获取到用户信息状态(google的API实现的),同时token被写入到cookie

6. 用户再次访问oidc.cnadn.net/mysecurit, 这次带了auth_token Cookie上来,因此JWT开始验证,如果通过则显示最终内容,即http://127.0.0.1:8080的内容:

1
2
3
4
5
6
7
    location /mysecurit {
    default_type text/html;
    set $email $http_x_jwt_email;
        set $name $auth_resp_x_vouch_idp_claims_blog$http_x_jwt_name;
        set $locale $http_x_jwt_locale;
    return 200 '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><h2>My securit is I know your:</h2><hr />Name: $name <br>email: $email <br>locale: $locale</html>';
}

过程记录

点击图片使用轮播模式

总结

利用NGINX plus的JWT模块实现在implicit模式下,作为资源服务器的replying part来对token进行验证。

对本文的最后一个系列,关于NGINX代理资源服务器进行token introspection验证模式,由于只是token验证形式的不同,对于oAuth整个流程来说都一样的,因此就不再重复阐述了,请直接参考:

oauth2-token-introspection-plus Plus可以将验证临时缓存在内存里,加速性能
oauth2-token-introspection-oss
Validating OAuth 2.0 Access Tokens with NGINX and NGINX Plus

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: nginx oAuth2 OIDC
最后更新:2020年05月22日

纳米

http://linjing.io

打赏 点赞
< 上一篇
下一篇 >

文章评论

取消回复

纳米

http://linjing.io

☁️迈向Cloud Native ADC ☁️

认证获得:
Kubernetes: CKA #664
Microsoft: MCSE MCDBA
Cisco: CCNP
Juniper: JNCIS
F5:
F5 Certified Solution Expert, Security
F5 Certified Technology Specialist, LTM/GTM/APM/ASM
F5 Certified BIG-IP Administrator
  • 点击查看本博技术要素列表
  • 分类目录
    • Avi Networks (3)
    • Cisco ACI (1)
    • CISCO资源 (21)
    • F5 with ELK (8)
    • F5-Tech tips (38)
    • F5技术 (203)
    • Juniper (4)
    • Linux (7)
    • Nginx (18)
    • SDN (4)
    • ServiceMesh (19)
    • WEB编程 (8)
    • WINDOWS相关 (7)
    • 业界文章 (18)
    • 交换机技术 (20)
    • 化云为雨/Openstack (35)
    • 协议原理 (52)
    • 容器/k8s (64)
    • 我的工作 (19)
    • 我的生活 (70)
    • 网站技术 (19)
    • 路由器技术 (80)
    • 项目案例 (28)
    文章归档
    标签聚合
    F5 k8s openstack nginx istio DNS envoy gtm docker network flannel api irule bigip neutron cc kubernetes ELK vxlan BGP dhcp VPN IPSec lbaas ingress ingress controller nginx plus sidecar IPSec VPN NAT sql
    最新 热点 随机
    最新 热点 随机
    Say hello for 2021 二进制flannel部署,非cni网络模式下与k8s CIS结合方案 又是一年国庆 Service Account Token Volume Projection Istio ingressgateway 静态TLS证书加载与SDS发现方式配置区别 Istio里Gateway的port定义与实际ingressgateway的listener端口关系及规则 Helm 3 部署NGINX Ingress Controller 应用交付老兵眼中的Envoy, 云原生时代下的思考 Istio sidecar iptables以及流量控制分析 Istio 熔断策略及envoy配置
    Say hello for 2021
    聊聊为啥kubernetes的dashboard搞起来这么费劲 soap 协议 2 F5在防范攻击上的措施 F5-v10-远程管理认证 授权 之 tacacs+/Radius/ldap版 ADC Magic Quadrant 2015 特洛伊产品体验活动.不只是木马! 双工问题 网通地址段 这个更全些 【案例】F5在铁路12306中的应用 How to config GTM with 3rd-party certificates
    链接表
    • Jimmy Song‘s Blog
    • SDNap
    • SDNlab
    • SDN论坛
    • Service Mesh社区
    • 三斗室
    • 个人profile

    COPYRIGHT © 2020 Cloud Native应用交付. ALL RIGHTS RESERVED.

    THEME KRATOS MADE BY VTROIS

    京ICP备14048088号-1

    京公网安备 11010502041506号

    [ Placeholder content for popup link ] WordPress Download Manager - Best Download Management Plugin