【问题标题】:Update/convert 'flask_oauthlib.client' to 'authlib.flask.client' - Microsoft Graph v2 access without a user将“flask_oauthlib.client”更新/转换为“authlib.flask.client” - 无需用户即可访问 Microsoft Graph v2
【发布时间】:2019-03-10 11:45:11
【问题描述】:

我的目标是实现这一点: https://github.com/Azure-Samples/active-directory-python-flask-graphapi-web-v2

使用更新的 Authlib 库。 https://github.com/lepture/authlib

我需要一个使用证书进行身份验证(无需用户登录)并使用 Microsoft 的 Graph API 从 Azure AD(v2.0 端点)SharePoint Document 库中获取数据的应用程序。

这是使用'flask_oauthlib'的原始代码:

from flask import Flask, redirect, url_for, session, request, jsonify, render_template
from flask_oauthlib.client import OAuth, OAuthException

# from flask_sslify import SSLify

from logging import Logger
import uuid

app = Flask(__name__)
# sslify = SSLify(app)
app.debug = True
app.secret_key = 'development'
oauth = OAuth(app)

# Put your consumer key and consumer secret into a config file
# and don't check it into github!!
microsoft = oauth.remote_app(
    'microsoft',
    consumer_key='Register your app at apps.dev.microsoft.com',
    consumer_secret='Register your app at apps.dev.microsoft.com',
    request_token_params={'scope': 'offline_access User.Read'},
    base_url='https://graph.microsoft.com/v1.0/',
    request_token_url=None,
    access_token_method='POST',
    access_token_url='https://login.microsoftonline.com/common/oauth2/v2.0/token',
    authorize_url='https://login.microsoftonline.com/common/oauth2/v2.0/authorize'
)


@app.route('/')
def index():
    return render_template('hello.html')

@app.route('/login', methods = ['POST', 'GET'])
def login():

    if 'microsoft_token' in session:
        return redirect(url_for('me'))

    # Generate the guid to only accept initiated logins
    guid = uuid.uuid4()
    session['state'] = guid

    return microsoft.authorize(callback=url_for('authorized', _external=True), state=guid)

@app.route('/logout', methods = ['POST', 'GET'])
def logout():
    session.pop('microsoft_token', None)
    session.pop('state', None)
    return redirect(url_for('index'))

@app.route('/login/authorized')
def authorized():
    response = microsoft.authorized_response()

    if response is None:
        return "Access Denied: Reason=%s\nError=%s" % (
            response.get('error'),
            request.get('error_description')
        )

    # Check response for state
    print("Response: " + str(response))
    if str(session['state']) != str(request.args['state']):
        raise Exception('State has been messed with, end authentication')

    # Okay to store this in a local variable, encrypt if it's going to client
    # machine or database. Treat as a password.
    session['microsoft_token'] = (response['access_token'], '')

    return redirect(url_for('me'))

@app.route('/me')
def me():
    me = microsoft.get('me')
    return render_template('me.html', me=str(me.data))



# If library is having trouble with refresh, uncomment below and implement refresh handler
# see https://github.com/lepture/flask-oauthlib/issues/160 for instructions on how to do this

# Implements refresh token logic
# @app.route('/refresh', methods=['POST'])
# def refresh():

@microsoft.tokengetter
def get_microsoft_oauth_token():
    return session.get('microsoft_token')

if __name__ == '__main__':
    app.run()

这是我目前更新为 'authlib.flask' 的代码:

from flask import Flask
from flask import redirect, url_for, session, request, jsonify, render_template
from authlib.flask.client import OAuth
from logging import Logger

import uuid


app = Flask(__name__)

app.debug = True
app.secret_key = 'development'
oauth = OAuth(app)

# Put your consumer key and consumer secret into a config file
    # and don't check it into github!!
microsoft = oauth.register(
    'microsoft',
    client_id='Register your app at apps.dev.microsoft.com',
    client_secret='Register your app at apps.dev.microsoft.com',
    request_token_params={'scope': 'offline_access User.Read'},
    api_base_url='https://graph.microsoft.com/v1.0/',
    request_token_url=None,
    access_token_method='POST',
    access_token_url='https://login.microsoftonline.com/common/oauth2/v2.0/token',
    authorize_url='https://login.microsoftonline.com/common/oauth2/v2.0/authorize',
)

@app.route('/')
def index():
    return render_template('hello.html')

@app.route('/login', methods = ['POST', 'GET'])
def login():
    if 'microsoft_token' in session:
        return redirect(url_for('me'))

    # Generate the guid to only accept initiated logins
    guid0 = uuid.uuid4()
    guid = guid0.bytes
    session['state'] = guid

    return microsoft.authorize_redirect(url_for('authorized', _external=True), state=guid)

@app.route('/logout', methods = ['POST', 'GET'])
def logout():
    session.pop('microsoft_token', None)
    session.pop('state', None)
    return redirect(url_for('index'))

@app.route('/login/authorized')
def authorized():
    response = microsoft.authorize_access_token()

    if response is None:
        return "Access Denied: Reason=%s\nError=%s" % (
            response.get('error'),
            request.get('error_description')
        )

    # Check response for state
    print("Response: " + str(response))
    if str(session['state']) != str(request.args['state']):
        raise Exception('State has been messed with, end authentication')

    # Okay to store this in a local variable, encrypt if it's going to client
    # machine or database. Treat as a password.
    session['microsoft_token'] = (response['access_token'], '')

    return redirect(url_for('me'))

@app.route('/me')
def me():
    me = microsoft.get('me')
    return render_template('me.html', me=str(me.data))


# If library is having trouble with refresh, uncomment below and implement refresh handler
# see https://github.com/lepture/flask-oauthlib/issues/160 for instructions on how to do this

# Implements refresh token logic
# @app.route('/refresh', methods=['POST'])
# def refresh():

@microsoft.tokengetter
def get_microsoft_oauth_token():
    return session.get('microsoft_token')

if __name__ == '__main__':
    app.run()

我坚持的部分是如何处理:

@microsoft.tokengetter
def get_microsoft_oauth_token():
    return session.get('microsoft_token')

“将 OAuth 客户端从 Flask-OAuthlib 迁移到 Authlib”中的 Authlib 文档说明如下:

如果您想使用以下方法访问资源 oauth.twitter.get(...),你需要确保有一个准备好 使用访问令牌。这部分在 Flask-OAuthlib 之间有很大不同 和 Authlib。

在 Flask-OAuthlib 中,它由装饰器处理:

 @twitter.tokengetter
 def get_twitter_oauth_token():
     token = fetch_from_somewhere()
     return token

tokengetter 返回的令牌可以是元组或字典。但在 Authlib,它只能是一个dict,而Authlib不使用装饰器来 相反,您应该将此函数传递给注册表:

 # register the two methods oauth.register('twitter',
     client_id='Twitter Consumer Key',
     client_secret='Twitter Consumer Secret',
     request_token_url='https://api.twitter.com/oauth/request_token',
     request_token_params=None,
     access_token_url='https://api.twitter.com/oauth/access_token',
     access_token_params=None,
     refresh_token_url=None,
     authorize_url='https://api.twitter.com/oauth/authenticate',
     api_base_url='https://api.twitter.com/1.1/',
     client_kwargs=None,
     # NOTICE HERE
     fetch_token=fetch_twitter_token,
     save_request_token=save_request_token,
     fetch_request_token=fetch_request_token, )

https://blog.authlib.org/2018/migrate-flask-oauthlib-client-to-authlib

我不知道如何处理“@microsoft.tokengetter”

有人有什么建议吗?

【问题讨论】:

    标签: python-3.x flask graph flask-oauthlib authlib


    【解决方案1】:

    在http://docs.authlib.org/en/latest/flask/client.html#flask-client查看文档

    您的问题中有一些无效代码:

    1. session['state']没用,请删除相关代码
    2. request_token_params 仅用于 OAuth1
    3. 和天蓝色的例子:https://github.com/authlib/loginpass/blob/master/loginpass/azure.py

    【讨论】:

    • 太棒了,谢谢!我会看看并尝试一下。
    • lepture,请看我上面的帖子,我无法回复你这么多字符。
    【解决方案2】:

    散文

    在http://docs.authlib.org/en/latest/flask/client.html#flask-client查看文档

    您的问题中有一些无效代码:

    1. session['state']没用,请删除相关代码
    2. request_token_params 仅用于 OAuth1
    3. 和天蓝色的例子:https://github.com/authlib/loginpass/blob/master/loginpass/azure.py

    如果你有机会,我有一些澄清。

    我想使用 Flask,在您的烧瓶示例中,我没有看到 Azure 的字段。 在 config.py 中,我是否需要像所有其他网站一样为 azure 添加一个部分:

    SECRET_KEY = b'secret'
    TWITTER_CLIENT_ID = ''
    TWITTER_CLIENT_SECRET = ''
    

    改成?:

    SECRET_KEY = b'secret'
    AZURE_CLIENT_ID = ''
    AZURE_CLIENT_SECRET = ''
    

    然后我想我只需要 loginpass 文件夹中的 init、_const、_core、_flask 和 azure py 文件。 然后我需要来自 flask_example 文件夹的应用程序和配置 py 文件,并从 loginpass 导入 azure。

    我的想法正确吗?

    【讨论】:

    • 它们只是让您了解其工作原理的示例。您可以从我提供的代码中了解如何实现 Azure 集成。
    • 好的,谢谢。我对烧瓶和 python 很陌生。我正在尝试自己学习如何做到这一点。当我有机会时,我会玩弄它,这个登录密码对我来说似乎有点困惑(作为新手)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多