您的位置:首页 > 移动开发 > 微信开发

移动端获得微信openid_构建用于移动设备的OpenID Connect流

2020-08-02 06:18 211 查看

移动端获得微信openid

Finding precise guidelines on how to implement OpenID Connect for native mobile apps is a harsh journey. Most resources available don’t follow best practices and the other ones leave some important questions unanswered.

寻找有关如何为本地移动应用程序实施OpenID Connect的精确指南是艰巨的旅程。 可用的大多数资源都没有遵循最佳实践,而其他资源则留下了一些重要问题未得到解答。

The goal here is not to reinvent the wheel, but to present a simple yet complete & robust implementation of OpenID Connect flow for mobile. It is based on the Authentication Code Flow, complies with the last official guidelines available RCF 8252 and IETF OAuth 2.0 Security Best Practices, and is fully compatible with the OpenID Connect Foundation Android SDK and OpenID Connect Foundation iOS SDK.

这里的目标不是重新发明轮子,而是提出一种简单而完整且健壮的针对移动设备的OpenID Connect流实现。 它基于身份验证代码流 ,符合最新的RCF 8252IETF OAuth 2.0安全最佳实践官方指南,并且与OpenID Connect Foundation Android SDKOpenID Connect Foundation iOS SDK完全兼容。

做出的选择 (Choices made)

Opinionated choices have been made for this implementation.

为此实现做出了有选择的选择。

1. Use the Authorization Code Grant flow

1.使用授权码授予流程

Given the vulnerability of the Implicit Grant flow, the Authorization Code Grant flow is the one that should be used from now on.

考虑到隐式授予流程脆弱性授权码授予流程是从现在开始应使用的流程。

2. Use the browser for authentication

2.使用浏览器进行身份验证

Thinking about an authentication flow on mobile, it is quite intuitive to go with a native implementation. However, keeping the authentication part in the browser helps you achieve important goals :

考虑到移动设备上的身份验证流程,采用本机实现非常直观。 但是,将身份验证部分保留在浏览器中可帮助您实现重要目标:

  • security: by going through the browser and using the web authentication form of the Authorization server, you instantly benefit from security mechanisms they may already implements (ie : sandboxing, certificates validation, …).

    安全性:通过浏览器并使用授权服务器的Web身份验证表单,您可以立即从它们可能已经实现的安全性机制(例如:沙箱,证书验证等)中受益。
  • user trust: you may think that a native implementation is always more efficient. However, from a user point of view, having to provide his third party credentials directly in your application seems like a potential security issue. How could he know that you are not going to steal his credentials along the way ?

    用户信任:您可能会认为本机实现总是效率更高。 但是,从用户的角度来看,必须直接在您的应用程序中提供第三方凭据似乎是潜在的安全问题。 他怎么会知道您一路上不会窃取他的证书?
  • maintainability: when authentication goes through the browser, the authentication flow is delegated to the Authorization server. So what happens if the authorization server wants to enforce new mechanisms (ie : 2-factors authentication, user consent, …) ? Nothing on your side. It will be completely transparent for your application.

    可维护性:通过浏览器进行身份验证时,身份验证流程将委派给授权服务器。 那么,如果授权服务器想要实施新的机制(即2要素身份验证,用户同意等),会发生什么? 什么都没有在你身边。 对于您的应用程序,它将是完全透明的。

3.采取简单的路径将
client_secret
保密 (3. Take a simple path to keep the
client_secret
secret)

Any secret bundled with a mobile application shouldn’t be considered a secret. AppAuth and RCF 8252 — section-5.3.3 emphasize this and state that to ensure that the

client_secret
should be kept server-side. Perfect, let's keep it server side but storing this secret in a "proxy" ! But as soon as you do that, you realize that without a strong authentication between your client application and your server, your
client_secret
will be kept secret but anybody can impersonate your application through your proxy. So any attacker catching the OAuth authentication "code" will be able to impersonate your app through your proxy and getting the user "access_token" from it.

与移动应用程序捆绑在一起的任何秘密都不应视为秘密。 AppAuthRCF 8252(第5.3.3节)强调了这一点,并声明应确保将

client_secret
保留在服务器端。 完美,让我们保留它在服务器端,但是将这个秘密存储在“代理”中! 但是,一旦您这样做,您就会意识到,如果没有在客户端应用程序和服务器之间进行强身份验证,则
client_secret
将会被保密,但是任何人都可以通过代理来模拟您的应用程序。 因此,任何捕获OAuth身份验证“代码”的攻击者都可以通过您的代理模仿您的应用,并从中获取用户“ access_token”。

Proof Key for Code Exchange (PKCE) has been created to prevent this without requiring a strong authentication between the client and the server. Used in conjunction with a mechanism preventing MITM attacks between your application and your server,

client_secret
will be able to be kept securely server-side while preventing anybody to perform a user authentication on your behalf.

已创建代码交换证明密钥(PKCE),以防止这种情况,而无需在客户端和服务器之间进行严格的身份验证。 与防止应用程序和服务器之间发生MITM攻击的机制结合使用,

client_secret
将能够安全地保留在服务器端,同时防止任何人代表您执行用户身份验证。

4.不支持一切 (4. Do not support everything)

Android App links and iOS Universal Links support is key to this implementation. They require Android >= 6.0 Marshmallow and iOS >= 9. Since both were released in 2015, this shouldn’t be too much of a problem by now.

Android App链接iOS Universal Links支持是此实现的关键。 他们需要Android> = 6.0 Marshmallow和iOS> =9。自从两者都于2015年发布以来,现在这应该不是太大的问题。

抽象流程 (Abstract Flow)

详细流程 (Detailed Flow)

Authentication is done in the browser by calling the authorize endpoint of the authorization server. This endpoint is often

GET /authorize
but it could be something else, depending on the authorization server configuration.

通过调用授权服务器的授权端点在浏览器中完成身份验证。 该端点通常是

GET /authorize
但也可以是其他端点,具体取决于授权服务器的配置。

GET <AUTHORIZATION_SERVER_URL>/authorize?
response_type=code
&scope=openid email profile
&client_id=<CLIENT_ID>
&redirect_uri=<REDIRECT_URI>
&code_challenge_method=S256
&code_challenge=<PKCE_CHALLENGE>

response_type
As we are implementing the “Authorization Code Grant flow”, should always be
code
.

response_type
在实现“授权代码授予流”时,应始终为
code

scope
Define the OpenID Connect claims you are interested about, see Requesting Claims using Scope Values.

scope
定义您感兴趣的OpenID Connect声明,请参阅使用范围值请求声明

client_id
The identifiers of your application for the authorization server.

client_id
授权服务器的应用程序标识符。

redirect_uri
A valid URL recognized by your mobile application as an app link. It will allow to redirect the user back to your application after authentication and to get the “code” back from the authentication process.

redirect_uri
一个有效的URL,您的移动应用程序将其识别为应用程序链接。 它将在身份验证后将用户重定向回您的应用程序,并从身份验证过程中获取“代码”。

code_challenge_method
PKCE code challenge method,
S256
(SHA-256) MUST be used if the client supports it.

如果客户端支持,则必须使用

code_challenge_method
PKCE代码挑战方法
S256
(SHA-256)。

code_challenge
PKCE code challenge, see PKCE Protocol to implement it yourself or use AppAuth to handle it for you.

code_challenge
PKCE代码质询,请参阅PKCE协议自行实现或使用AppAuth为您处理。

Security concerns

安全问题

  • This authentication process should be handled using a registered browser or an “in-app browser tabs”, not a “web-view” (see RFC 8252).

    应使用注册的浏览器或“应用内浏览器选项卡”而非“网络视图”(请参阅RFC 8252 )来处理此身份验证过程。

  • You should use Android app links and iOS universal links, so only your application is able to get the authorization callback through

    redirect_uri
    .

    您应该使用Android应用程序链接iOS通用链接 ,因此只有您的应用程序才能通过

    redirect_uri
    获取授权回调。

  • You may want to restrict which browser is allowed for this process, AppAuth provides a mechanism to control which browser is used for authorization.

    您可能想要限制此过程允许使用的浏览器,AppAuth提供了一种机制来控制使用哪个浏览器进行授权

  • If your authentication server does not support PKCE, the

    code_challenge
    and
    code_challenge_method
    parameters won't be supported. In this case, at least use the
    state
    parameter to prevent CSRF attacks (see https://tools.ietf.org/html/draft-ietf-oauth-security-topics-15#section-4.7.1).

    如果您的身份验证服务器不支持PKCE,则将不支持

    code_challenge
    code_challenge_method
    参数。 在这种情况下,请至少使用
    state
    参数来防止CSRF攻击(请参阅https://tools.ietf.org/html/draft-ietf-oauth-security-topics-15#section-4.7.1)。

2.获取令牌和索偿 (2. Getting token & claims)

We will now go through our application server. We define a

POST /open_id_connect
endpoint on our server for this purpose. This endpoint will exchange the given
code
(and
code_verifier
) with the
access_token
and the
claims
from the authorization server.

现在,我们将遍历我们的应用程序服务器。

POST /open_id_connect
,我们在服务器上定义了一个
POST /open_id_connect
端点。 该端点将与给定的
code
(和
code_verifier
)与
access_token
和来自授权服务器的
claims
交换。

POST <APP_SERVER_URL>/open_id_connect?
code=<CODE>
&code_verifier=<CODE_VERIFIER>

code
The
code
returned by the authorization server to the
redirect_uri
on successful user authentication.

code
成功进行用户身份验证时,授权服务器返回到
redirect_uri
code

code_verifier
PKCE
code_verifier
that matches the
code_challenge
sent to the authorization server during authentication process.

code_verifier
PKCE
code_verifier
的匹配
code_challenge
在认证过程中发送到授权服务器。

Response

响应

In our implementation we also add an

account
property that will provide info on the existing user account on the platform (if any).

在我们的实现中,我们还添加了一个

account
属性,该属性将提供有关平台上现有用户帐户(如果有)的信息。

Response (no account associated to these credentials)

响应(没有与这些凭据关联的帐户)

{
"access_token": "<oauth_access_token>",
"claims": {
"sub": "<oauth_sub>",
"email": "<oauth_email>",
"given_name": "<oauth_first_name>",
"family_name": "<oauth_last_name>"
},
"account": null
}

Response (associated account already exits)

响应(关联帐户已存在)

{
"access_token": "<oauth_access_token>",
"claims": {
"sub": "<oauth_sub>",
"email": "<oauth_email>",
"given_name": "<oauth_first_name>",
"family_name": "<oauth_last_name>"
},
"account": { ... }
}

Security concerns

安全问题

(2之二)。 获取令牌和索偿 ((2 bis). Getting token & claims)

Behind the scene, your app server will have to call the authentication server to gather info.

在后台,您的应用服务器将不得不调用身份验证服务器来收集信息。

Calling the token endpoint

调用令牌端点

This call will allow your app server to exchange the

code
with an
access_token
.

通过此调用,您的应用服务器可以与

access_token
交换
code

curl -X POST '<AUTHORIZATION_SERVER_URL>/token' \
-H "Content-Type: application/x-www-form-urlencoded" \
-d 'grant_type=authorization_code' \
-d 'client_id=<CLIENT_ID>' \
-d 'client_secret=<CLIENT_SECRET>' \
-d 'redirect_uri=<REDIRECT_URI>' \
-d 'code=<CODE>' \
-d 'code_verifier=<PKCE_CODE_VERIFIER>'

Calling the userinfo endpoint

调用userinfo端点

This call will allow your app server to get the “claims” requested during authentication (giving the same

scope
parameter).

通过此调用,您的应用服务器可以获取身份验证期间请求的“声明”(提供相同的

scope
参数)。

curl -X POST '<AUTHORIZATION_SERVER_URL>/userinfo' \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-d 'client_id=<CLIENT_ID>' \
-d 'client_secret=<CLIENT_SECRET>' \
-d 'scope=openid profile email'

而已 ! (That’s it !)

You now know the end-user identity from the authorization server (

access_token
and
claims
) and if the user is already registered on your server (
account
). So you can decide if the end-user need a "sign-up" or a "sign-in", and use the gathered info to support these processes.

现在,您可以从授权服务器(

access_token
claims
)中了解最终用户的身份,以及该用户是否已经在您的服务器(
account
)上注册。 因此,您可以决定最终用户是否需要“注册”或“登录”,并使用收集的信息来支持这些过程。

Building a simple & secure OpenID Connect authentication flow on mobile is quite simple, if you follow the right guidelines ;-) Happy to answer any suggestions !

如果您遵循正确的准则,则在移动设备上构建简单且安全的OpenID Connect身份验证流程非常简单;-)乐意回答任何建议!

翻译自: https://medium.com/klaxit-techblog/openid-connect-for-mobile-apps-fcce3ec3472

移动端获得微信openid

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐