sign in with apple

1,参考文献

https://sarunw.com/posts/sign-in-with-apple-4/#create-a-sign-in-with-apple-private-key

2,实现代码

#! /usr/bin/env python
# -*- coding: utf-8 -*-
import jwt
import time
from tornado import gen
from tornado.log import gen_log

from hd_lib.utils.http_client import async_request
from hd_lib.utils.request_context import g_tn


PRIVATE_KEY_TOKEN = '''-----BEGIN PRIVATE KEY-----
xxxxxxx
-----END PRIVATE KEY-----
'''  # sign in with apple


class AppleHelper(object):

    @staticmethod
    def get_client_secret():
        return jwt.encode(
            payload={
                "iss": "xxxxxx",
                "iat": time.time() - 10,
                "exp": time.time() + 3500,
                "aud": "https://appleid.apple.com",
                "sub": "xxxxxx"
            },
            key=PRIVATE_KEY_TOKEN,
            headers={
                "alg": "ES256",
                "kid": "xxxxx",
                "typ": "JWT"
            },
            algorithm="ES256"
        )


class AppleService(object):
    AUTH_PATH = "https://appleid.apple.com/auth/token"  # 认证接口
    REVOKE_PATH = "https://appleid.apple.com/auth/revoke"  # 注销认证接口
    HEADERS = {"content-type": "application/x-www-form-urlencoded"}
    COMMON_DATA = {
        "client_id": "xxxxx",
        "client_secret": AppleHelper.get_client_secret()
    }

    @classmethod
    @gen.coroutine
    def send_request(cls, url, data):
        data.update(cls.COMMON_DATA)
        ret = yield async_request(g_tn(), url,
                                  data=data,
                                  method='POST',
                                  headers=cls.HEADERS,
                                  timeout=10,
                                  request_is_json=False)
        raise gen.Return(ret)

    @classmethod
    @gen.coroutine
    def revoke(cls, refresh_token, access_token):
        if not refresh_token:
            gen_log.info('<seq_no=%s> not refresh_token: refresh_token=%s', g_tn().seq_no, refresh_token)
            return
        # apple那里要求我们注销 refresh_token 和 access_token。
        # 但是 access_token 本身就是有过期时间的,我们只注销用户登录当时的那个 access_token,不再刷新 access_token 后再次注销。
        ret = yield cls.revoke_access_token(access_token)
        gen_log.info('<seq_no=%s> revoke_access_token: access_token=%s ret=%s', g_tn().seq_no, access_token, ret)
        ret = yield cls.revoke_refresh_token(refresh_token)
        gen_log.info('<seq_no=%s> revoke_refresh_token: refresh_token=%s ret=%s', g_tn().seq_no, refresh_token, ret)
        return

    @classmethod
    @gen.coroutine
    def auth_grant_code(cls, code):
        """
        通过 code 获取 access_token 和 refresh_token
        @param code:
        @return: {
                  "access_token": "adg61...67Or9",
                  "token_type": "Bearer",
                  "expires_in": 3600,
                  "refresh_token": "rca7...lABoQ"
                  "id_token": "eyJra...96sZg"
                }
        """
        data = {
            "code": code,
            "grant_type": "authorization_code",
        }
        ret = yield cls.send_request(cls.AUTH_PATH, data)
        raise gen.Return(ret)

    @classmethod
    @gen.coroutine
    def refresh_token(cls, refresh_token):
        """
        通过 refresh_token 刷新 access_token
        @param refresh_token:
        @return: {
                  "access_token": "beg510...67Or9",
                  "token_type": "Bearer",
                  "expires_in": 3600,
                  "id_token": "eyJra...96sZg"
                }
        """
        data = {
            "grant_type": "refresh_token",
            "refresh_token": refresh_token,
        }
        ret = yield cls.send_request(cls.AUTH_PATH, data)
        raise gen.Return(ret)

    @classmethod
    @gen.coroutine
    def revoke_access_token(cls, access_token):
        """
        注销 access_token
        @param access_token:
        @return:
        """
        data = {
            "token": access_token,
            "token_type_hint": "access_token",
        }
        ret = yield cls.send_request(cls.REVOKE_PATH, data)
        raise gen.Return(ret)

    @classmethod
    @gen.coroutine
    def revoke_refresh_token(cls, refresh_token):
        """注销 refresh_token"""
        data = {
            "token": refresh_token,
            "token_type_hint": "refresh_token",
        }
        ret = yield cls.send_request(cls.REVOKE_PATH, data)
        raise gen.Return(ret)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值