每个软件工程师应了解的OAuth 2.0知识

OAuth 2.0 is the industry standard protocol for authorization.

OAuth 2.0是用于授权的行业标准协议。

When I read the above sentence on the OAuth 2.0 homepage I felt like this is the kind of knowledge that I should have in order to call myself a software engineer, so I started digging. I remember that I felt a little bit scared that I will have to break through a lot of knowledge that is difficult to learn, but it turned out alright, and I’ve decided to share what I’ve learned!

当我在OAuth 2.0主页上阅读以上句子时,我觉得这是我应该给自己打电话给软件工程师的那种知识, 因此我开始进行挖掘 。 我记得我有些害怕,因为我不得不突破很多难以学习的知识,但是事实证明还不错,我决定分享我所学到的知识!

What you’ll get from this article:

您将从本文中获得什么:

  • How OAuth 2.0 works

    OAuth 2.0的工作方式
  • How an application gets an access token

    应用程序如何获取访问令牌
  • How SPA and web server applications deal with OAuth

    SPA和Web服务器应用程序如何处理OAuth
  • Types of access token and their validation

    访问令牌的类型及其验证
Image for post

OAuth 2.0的工作方式 (How OAuth 2.0 works)

First of all, if you are like me, the official specifications are not always the best place to get a bigger picture of how OAuth works, as almost immediately you may overwhelmed by the amount of information (because it’s not one specification but a lot of them). To understand how OAuth works, let’s ask questions.

首先,如果您像我一样,正式的规范并不总是最好的地方来了解OAuth的工作原理,因为您可能马上就会被大量的信息淹没( 因为这不是一个规范,而是很多规范。他们 )。 要了解OAuth的工作原理,让我们提出问题。

OAuth解决什么问题? (What problem does OAuth solve?)

Let’s take for example an application where we want to see a user’s daily schedule, assuming that our user has a Google account with some data to get from calendar — but how we can ask the user for this data whilst considering security? That’s the moment where OAuth comes to play, but what is important is: OAuth doesn’t tell the application who you are, it just gives the application access to data which it asks for!

让我们以一个应用程序为例,假设我们的用户拥有一个Google帐户,其中包含要从日历中获取的一些数据,而我们希望查看该用户的日程安排,但是在考虑安全性的情况下如何在询问用户该数据的同时呢? 这是OAuth发挥作用的关键时刻,但是重要的是: OAuth不会告诉应用程序您是谁,它只是使应用程序可以访问它所要求的数据

OAuth如何解决它? (How does OAuth solve it?)

The simple answer is, by giving an access token which allows your client application to get the data it needs from a resource server. I would like to describe an analogy which helped me a lot to understand this:

简单的答案是,通过提供访问令牌,该令牌使您的客户端应用程序可以从资源服务器获取所需的数据。 我想描述一个比喻,它对我有很多帮助:

Let’s assume you work for a bigger company where you have to use an access card to get in. This card has been given to you on the first day of work with proper permissions by a person which knows that you are a new employee. After that first day you use this card to get into the company and nobody checks your identity anymore, you just put your access card to the reader and the door will open. Furthermore, you cannot open all doors but just this one which allows you to do your everyday job tasks. OAuth is based on this kind of flow.

假设您在一家较大的公司工作,您必须使用门禁卡进入。该卡是在上班的第一天,由一位知道您是新员工的人以适当的权限提供给您的。 在第一天之后,您使用这张卡进入公司,而没人再检查您的身份了,您只需将访问卡放到阅读器上,门就会打开。 此外,您无法打开所有的门 ,只有 扇门可以完成日常工作。 OAuth基于这种流程。

Conclusions:

结论

  • You are verified on the first day and receive an access card which you can use every day

    您将在第一天通过验证,并会收到一张每天均可使用的访问卡
  • Every reader opens the door for you (if access to this area has been granted to you)

    每个读者都会为您打开一扇门( 如果已授予您进入该区域的权限 )

  • The reader doesn’t know anything about your identity, the only thing that is important for the reader is if you have a valid access card in your hand.

    读者不知道你的身份事情 ,那就是为读者唯一重要的事情是,如果你在你的手有效的准入证。

Image for post

应用程序如何获得访问令牌? (How does an application get an access token?)

From an apps perspective, the goal is to get an access token and then get data thanks to this token — so how does an app get an access token?

从应用程序的角度来看,目标是获取访问令牌,然后借助此令牌获取数据-那么应用程序如何获取访问令牌?

Ways to obtain a token by OAuth:

通过OAuth获取令牌的方式:

  • Authorization Code Flow (web apps, native apps)

    授权代码流(Web应用程序,本机应用程序)
  • Device Flow (AppleTV)

    设备流(AppleTV)
  • Password (for first-party apps)

    密码(适用于第一方应用)
  • Client Credentials (machine to machine)

    客户凭证(机器对机器)

Authorization Code Flow is most common approach, as it is used on both the web and in native applications. Before we can answer the question of how it actually works in OAuth one more thing we need to know is what kind of roles exists in OAuth.

授权代码流是最常见的方法,因为它同时在Web和本机应用程序中使用。 在我们可以回答它在OAuth中实际上如何工作的问题之前,我们需要知道的另一件事是OAuth中存在哪种角色

OAuth Roles:

OAuth角色:

  • User (Resource owner)*

    用户(资源所有者)*
  • Device (User agent)

    设备(用户代理)
  • Application (Client)

    应用程序(客户端)
  • OAuth server (Authorization server, where access token comes from)

    OAuth服务器(访问令牌来自的授权服务器)
  • API (Resource server)

    API(资源服务器)

*names in parentheses are those used in OAuth spec

*括号中的名称是OAuth规范中使用的名称

A proper diagram can be worth more than a thousand words:

一个正确的图表可能价值一千多个字:

Image for post
Getting an access token
获取访问令牌
  1. User logs in to the application;

    用户登录到应用程序;
  2. Application request user for access to some data (Google Calendar) and redirects the user to OAuth server;

    应用程序请求用户访问某些数据(Google日历),并将用户重定向到OAuth服务器;
  3. User logs in to an OAuth server with credentials;

    用户使用凭据登录到OAuth服务器;
  4. OAuth server returns a temporary code which will be then exchanged for an access token by app;

    OAuth服务器返回一个临时代码,然后由应用程序将其交换为访问令牌;
  5. User sends temporary code to the app;

    用户向应用发送临时代码;
  6. The application exchanges the code for an access token;

    应用程序将代码交换为访问令牌。
  7. The OAuth server returns an access token for the app;

    OAuth服务器返回该应用程序的访问令牌;
  8. The app uses the access token to get some data from a resource server;

    该应用程序使用访问令牌从资源服务器获取一些数据。
  9. Resource server returns user data to the application.

    资源服务器将用户数据返回到应用程序。

Off-topic: The application logo on the above diagram isn’t there by accident, it’s my newly created app to betting with friends. I named it Betbitly, check more if you are curious.

题外话:上图的应用程序徽标不是偶然出现的,这是我新创建的与朋友打赌的应用程序。 我将其命名为Betbitly ,如果您感到好奇,请进一步检查。

This access token flow can be a divided into two channels:

此访问令牌流可以分为两个通道:

🍎 Front channel (red lines)

🍎 前通道 (红线)

Data is sent via the URL and because of that request/response can be tampered by user/malicious software. In this kind of situation, someone to not seeing someone that you add access token. Both sides don’t know if data has not been tampered or sent from unwanted sources. Someone can change data along the way.

数据是通过URL发送的,由于该请求/响应,用户/恶意软件可能会对其进行篡改。 在这种情况下,有人看不到您添加访问令牌的人。 双方都不知道数据是否未被篡改或从有害来源发送。 有人可以沿途更改数据。

You can imagine a situation where you send a letter to your friend which doesn’t have letterbox and you don’t choose an option to delivery to the owners hands, so the postman may leave the letter at the the front door, so until your friend returns home, somebody else can get at this letter and change something in it. In this case, neither you nor your friend can be 100% sure that the letter has not been changed, by an uninvited person. Why even use a front channel in this case?

您可以想象这样一种情况:您向没有信箱的朋友发送了一封信,并且没有选择传递给所有者的选项,因此邮递员可能会将信留在前门,因此直到朋友回家后,其他人可以得到这封信并对其进行更改。 在这种情况下,您和您的朋友都无法百分百确定一个不请自来的人没有更改这封信。 在这种情况下,为什么还要使用前置声道?

The front channel is necessary because it is a natural interface to communicate with users to authorize an application to use data from the resource server, another example can be a mobile device.

前通道是必需的,因为它是与用户通信以授权应用程序使用来自资源服务器的数据的自然接口,另一个示例可以是移动设备。

🍏 Back channel (green lines)

🍏 反向通道 (绿线)

This is the secure part of communication because it is sent from an application to the server over HTTPS (and cannot be tampered with).

这是通信的安全部分,因为它是通过HTTPS从应用程序发送到服务器的(不能被篡改)。

In our analogy with the letter, it will be an option to deliver a letter to the owners hands.

与信件类似,可以选择将信件交给所有者。

结论: (Conclusions:)

  • OAuth can obtain an access token in four different ways

    OAuth可以通过四种不同方式获取访问令牌
  • There are five different type o OAuth roles

    OAuth角色共有五种
  • The way how the application obtains user’s data can be divided on two channels (front, back)

    应用程序获取用户数据的方式可以分为两个渠道(前,后)
Image for post

更深入地介绍两种类型的客户! (Go deeper, two types of clients!)

In terms of application possibility to keep a secret we can divide it again on two types of clients:

在保密的应用程序可能性方面,我们可以将其再次划分为两种类型的客户端:

Confidential Clients (application runs on server) which can keep a secretand Public Clients (SPA or native) which cannot.

机密客户端 (应用程序在服务器上运行)可以保留秘密 ,而公用客户端( SPA或本机)则不能。

Keeping in mind this division, I will describe what a request looks like on each of these types. It will be four requests, two for authorization and two for getting access token (the numbers refers to the numbers on the schema).

牢记这一划分,我将描述每种类型的请求的外观。 这将是四个请求,两个用于授权 ,两个用于获取访问令牌 ( 数字表示架构上的数字 )。

Authorization (front channel 🍎)

授权(前频道 🍎 )

  1. User => OAuth server (3)

    用户=> OAuth服务器(3)
  2. OAuth server => User (5)

    OAuth服务器=>用户(5)

Getting an Access Token (back channel 🍏)

获取访问令牌(反向通道 🍏 )

  1. Application => OAuth server (6)

    应用程序=> OAuth服务器(6)
  2. OAuth server => Application (7)

    OAuth服务器=>应用程序(7)

Web服务器应用程序(可信客户端) (Web server application (Confidental Clients))

Authorization (front channel 🍎)

授权(前频道 🍎 )

It’s worth mentioning just a bit about Scope here. Scope guarantees an application only has access to data which was requested during login (of a user to an OAuth server). Users should always should be which data access has been granted.

这里值得一提的是Scope 。 范围保证了应用程序只能访问(用户登录到OAuth服务器)登录期间请求的数据。 用户应始终应被授予了哪些数据访问权限。

Image for post

If a user allows an application access to resources, the OAuth server will respond with code which then will be exchanged by the application for the access token:

如果用户允许应用程序访问资源,则OAuth服务器将以代码作为响应,然后由应用程序将其交换为访问令牌:

Getting access token (back channel 🍏)

获取访问令牌(反向通道 🍏 )

单页应用程序(公共客户端) (Single-Page Application (Public Clients))

This kind of an application cannot maintain client’s secret because it’s run entirely in the browser, so to preserve authorization code flow introduced above, have to generate secret on each request, at this is called PKCE which stands for Proof-Key for Code Exchange, so instead of sending client secret you send PKCE generated when every getting access token flow starts, to achieve this we have to change a little bit our previous web server authorization request (auth-req.web-server.js) by adding two ingredients:

这种应用程序不能完全维护客户端的机密,因为它完全在浏览器中运行,因此要保留上面介绍的授权代码流,必须在每个请求上生成机密,这称为PKCE,代表代码交换的证明密钥,因此为了实现此目的,我们不必更改我们的先前的Web服务器授权请求( auth-req.web-server.js ), 只需添加以下两种内容即可:

  • code verifier (random string 43–128 characters long)

    代码验证程序(随机字符串,长度为43–128个字符)
  • code challenge (url-safe base64-encoded SHA256 hash of the code verifier)

    代码质询(代码验证程序的URL安全base64编码的SHA256哈希)

Authorization (front channel 🍎)

授权(前频道 🍎 )

Getting access token (back channel 🍏)

获取访问令牌(反向通道 🍏 )

Mobile apps also cannot generate secret so we have to use PKCE secret there, to get more information I will recommend to visit aaronparecki site.

移动应用程序也无法生成秘密,因此我们必须在此处使用PKCE秘密,以获取更多信息,我建议您访问aaronparecki网站。

结论: (Conclusions:)

  • Two types of clients confidential and public;

    保密和公开两种类型的客户;
  • The confidential client can keep a secret (web server app);

    机密客户端可以保守秘密(Web服务器应用程序);
  • Public client can’t keep a secret (SPA);

    公开客户不能保守秘密(SPA);
  • PKCE instead of client secret in public client.

    PKCE,而不是公共客户端中的客户端机密。

访问令牌 (Access token)

访问令牌的类型 (Types of access token)

Reference token:

参考令牌:

  • Often storing in database

    经常存储在数据库中
  • Allow to every kind of operation which you can do with any standard database data, for example, show a list of active tokens

    允许您使用任何标准数据库数据执行的每种操作,例如,显示活动令牌的列表
  • Can be easy revoked (just delete from database)

    可以轻松撤销(只需从数据库中删除)
  • Use for smaller the application because of the requirement of storing all tokens.

    由于需要存储所有令牌,因此可用于较小的应用程序。

Self-Encoded Tokens:

自编码令牌:

  • Data live in the token itself (JWT)

    数据存在令牌本身(JWT)中
  • Don’t have to be storage

    不必存储
  • Separation of concerns, API doesn’t have to a storage access token

    分离关注点,API不必具有存储访问令牌
  • Valid at the API not with DB/HTTP lookup like in reference token

    在API上无效,不能像参考令牌中那样通过DB / HTTP查找
  • Cannot get a list of all active tokens

    无法获取所有活动令牌的列表
  • Better for bigger application

    更适合更大的应用

Access token validation

访问令牌验证

An access token has to be validated once it has been granted. It can become invalid from two reasons expiration or revocation.

授予访问令牌后,必须对其进行验证。 它可能由于到期或吊销的两个原因而变得无效。

Token expiration is related to expiration time, which is one of the properties returned from the OAuth server along with the rest of the data when the application exchange code received from the user to access token.

令牌过期与过期时间有关,令牌过期是从OAuth服务器返回的属性之一,当应用程序交换从用户那里收到的用于交换令牌的代码时,其余的数据也是如此。

Imagine a case where access token expiration is set on 1 hour but our application session is longer than that, for example, 4 hours. To deliver the best user experience we don’t want to ask the user to login 4 times in one session — to solve this issue we receive a refresh token along with access token from OAuth server which allows the application to get a new access token for the user in the background. The key difference between access and refresh token is lifetime cycle, the access token is short life so storing it doesn’t require such security as a reference token which has a long life cycle because if an attacker would steal it the consequences would be much worse.

假设有一个访问令牌过期设置为1小时,但我们的应用程序会话比这更长的时间,例如4小时。 为了提供最佳的用户体验,我们不想让用户在一个会话中登录4次-为了解决此问题,我们从OAuth服务器收到刷新令牌以及访问令牌,该令牌允许应用程序获取新的访问令牌后台的用户。 访问令牌和刷新令牌之间的主要区别是生命周期,访问令牌的寿命很短,因此存储它不需要像参考令牌那样具有较长生命周期的安全性,因为如果攻击者窃取它,后果将更糟。

Revocation is quite simple, it takes place when the user tells OAuth server that this token is no longer valid.

撤销非常简单,它在用户告诉OAuth服务器该令牌不再有效时发生。

Revoked token issue

撤销令牌发行

Note: Pay attention to the fact that if you only do local validation and your access token has expiration time like 4h and after 1h user revokes application to use data then local validation will still be passed because it doesn’t know anything about revokes operation, but if the application would ask OAuth server, of course, it will return, that token is invalid so in worst case scenario you can have an invalid token for 3h but locally it will be still valid, because of that you should process local validation for every protected HTTP request and then in your application decide which data are so sensitive to should make an additional request to OAuth server to check if a token hasn’t been revoked.

注意:请注意以下事实:如果您仅执行本地验证,并且访问令牌具有4h之类的到期时间,并且1h用户撤消应用程序以使用数据,则本地验证仍将通过,因为它对撤消操作一无所知,但是,如果应用程序询问OAuth服务器,则该令牌将无效,因此在最坏的情况下,您可以在3h内拥有一个无效的令牌,但在本地仍然有效,因为您应该处理本地验证每个受保护的HTTP请求,然后在您的应用程序中决定对哪些数据如此敏感,应该向OAuth服务器发出另一个请求,以检查令牌是否尚未撤消。

结论: (Conclusions:)

  • Two types of tokens reference and self-encoded

    两种类型的令牌参考和自编码
  • Token can expired or be revoked

    令牌可以过期或被撤销
  • Always ask OAuth server if an access token is still valid before processing security-sensitive operation

    在处理对安全敏感的操作之前,请始终询问OAuth服务器访问令牌是否仍然有效
Image for post

总结思想 (Closing thoughts)

These are the basics which (in my opinion) every software engineer should know about OAuth. I hope that it’s just a little bit more accessible than reading official specifications.

这些是(我认为)每个软件工程师都应该了解的有关OAuth的基础知识。 我希望它比阅读正式规范要容易一些。

As far as I’m concerned I’m still impressed with how good OAuth 2.0 works, and in terms of security it also looks very solid. It’s easy to understand the basic concept and flow of granting rights an application to the user’s data resources which stands behind it. No wonder than almost all application which uses 3rd-party login using OAuth 2.0.

就我而言,我仍然对OAuth 2.0的出色表现印象深刻,就安全性而言,它也非常可靠。 很容易理解为应用程序背后的用户数据资源授予权限的基本概念和流程。 难怪几乎所有使用OAuth 2.0使用第三方登录的应用程序都可以。

I hope now you are just a bit more familiar with OAuth, thanks for your time!

希望您现在对OAuth更加熟悉,感谢您的宝贵时间!

Stay in touch with me on Twitter or Github.

TwitterGithub上与我保持联系。

Image for post

📑资源 (📑 Resources)

[1] https://aaronparecki.com/oauth-2-simplified/#client-credentials[2] https://oauth.net/2[3] https://www.oauth.com

[1] https://aaronparecki.com/oauth-2-simplified/#client-credentials [2] https://oauth.net/2 [3] https://www.oauth.com

翻译自: https://medium.com/dailyjs/what-every-software-engineer-should-know-about-oauth-2-0-10f0ef4998e5

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值