2017-03-23 115 views
0

我正在測試各種oath2工作流程,而我正在努力的工作流程是Authorization Code Grantoath2 - 使用Flask授權代碼授權(訪問bitbucket)?

我可以成功獲取令牌如果我以簡單的方式複製/粘貼網址。

我的意思request accesscopy paste given URlenter it in a browseraccept authorizationcopy paste back callback url - >接入資源。就像這個例子:

from requests_oauthlib import OAuth2Session 


class ClientSecrets: 
    """ 
    The structure of this class follows Google convention for `client_secrets.json`: 
    https://developers.google.com/api-client-library/python/guide/aaa_client_secrets 
    Bitbucket does not emit this structure so it must be manually constructed. 
    """ 
    client_id = "myid" 
    client_secret = "mysecret" 
    auth_uri = "https://bitbucket.org/site/oauth2/authorize" 
    token_uri = "https://bitbucket.org/site/oauth2/access_token" 
    server_base_uri = "https://api.bitbucket.org/" 


def main(): 
    c = ClientSecrets() 
    # Fetch a request token 
    bitbucket = OAuth2Session(c.client_id) 
    # Redirect user to Bitbucket for authorization 
    authorization_url = bitbucket.authorization_url(c.auth_uri) 
    print('Please go here and authorize: {}'.format(authorization_url[0])) 
    # Get the authorization verifier code from the callback url 
    redirect_response = raw_input('Paste the full redirect URL here:') 
    # Fetch the access token 
    bitbucket.fetch_token(
     c.token_uri, 
     authorization_response=redirect_response, 
     username=c.client_id, 
     password=c.client_secret) 
    # Fetch a protected resource, i.e. user profile 
    r = bitbucket.get(c.server_base_uri + '1.0/user') 
    print(r.content) 

但如果我嘗試這樣做,用瓶模仿,試圖以訪問到位桶實際的Web應用程序,它無法獲得訪問權。

我的瓶的應用程序實現示例如下:

from flask import Flask, redirect, request, session 

from requests_oauthlib import OAuth2Session 

app = Flask(__name__) 

client_id = 'myid' 
client_secret = 'mysecret' 
authorization_base_url = 'https://bitbucket.org/site/oauth2/authorize' 
token_url = 'https://bitbucket.org/site/oauth2/access_token' 
redirect_uri = 'https://127.0.0.1:5000/callback' 


@app.route('/login') 
def login(): 
    oauth2 = OAuth2Session(client_id, redirect_uri=redirect_uri) 
    authorization_url, state = oauth2.authorization_url(
     authorization_base_url, 

    ) 
    # State is used to prevent CSRF, keep this for later. 
    session['oauth_state'] = state 
    return redirect(authorization_url) 


@app.route("/callback") 
def callback(): 
    bitbucket = OAuth2Session(client_id, state=session['oauth_state']) 
    bitbucket.fetch_token(
     token_url, 
     client_secret=client_secret, 
     authorization_response=request.url) 
    return bitbucket.get('some_resource_url').content 

if __name__ == '__main__': 
    # Certificate and key files. 
    context = ('cert/server.crt', 'cert/server.key') 
    app.run(debug=True, ssl_context=context) 

如果我運行的應用程序像例子中,然後我得到試圖訪問URL時,這個錯誤:https://127.0.0.1:5000/login

File "/home/oerp/python-programs/flask-app/bitiface/test.py", line 23, in login 
    session['oauth_state'] = state 
    File "/home/oerp/python-programs/flask-app/bitiface/venv/lib/python2.7/site-packages/werkzeug/local.py", line 350, in __setitem__ 
    self._get_current_object()[key] = value 
    File "/home/oerp/python-programs/flask-app/bitiface/venv/lib/python2.7/site-packages/flask/sessions.py", line 130, in _fail 
    raise RuntimeError('The session is unavailable because no secret ' 
RuntimeError: The session is unavailable because no secret key was set. Set the secret_key on the application to something unique and secret. 

它看起來像與oath_state聯繫的東西。如果我評論oath_state指定並嘗試像以前一樣運行應用程序。然後,我得到這個錯誤:

Traceback (most recent call last): 
    File "/home/oerp/python-programs/flask-app/bitiface/venv/lib/python2.7/site-packages/flask/app.py", line 1994, in __call__ 
    return self.wsgi_app(environ, start_response) 
    File "/home/oerp/python-programs/flask-app/bitiface/venv/lib/python2.7/site-packages/flask/app.py", line 1985, in wsgi_app 
    response = self.handle_exception(e) 
    File "/home/oerp/python-programs/flask-app/bitiface/venv/lib/python2.7/site-packages/flask/app.py", line 1540, in handle_exception 
    reraise(exc_type, exc_value, tb) 
    File "/home/oerp/python-programs/flask-app/bitiface/venv/lib/python2.7/site-packages/flask/app.py", line 1982, in wsgi_app 
    response = self.full_dispatch_request() 
    File "/home/oerp/python-programs/flask-app/bitiface/venv/lib/python2.7/site-packages/flask/app.py", line 1614, in full_dispatch_request 
    rv = self.handle_user_exception(e) 
    File "/home/oerp/python-programs/flask-app/bitiface/venv/lib/python2.7/site-packages/flask/app.py", line 1517, in handle_user_exception 
    reraise(exc_type, exc_value, tb) 
    File "/home/oerp/python-programs/flask-app/bitiface/venv/lib/python2.7/site-packages/flask/app.py", line 1612, in full_dispatch_request 
    rv = self.dispatch_request() 
    File "/home/oerp/python-programs/flask-app/bitiface/venv/lib/python2.7/site-packages/flask/app.py", line 1598, in dispatch_request 
    return self.view_functions[rule.endpoint](**req.view_args) 
    File "/home/oerp/python-programs/flask-app/bitiface/test.py", line 33, in callback 
    authorization_response=request.url) 
    File "/home/oerp/python-programs/flask-app/bitiface/venv/lib/python2.7/site-packages/requests_oauthlib/oauth2_session.py", line 244, in fetch_token 
    self._client.parse_request_body_response(r.text, scope=self.scope) 
    File "/home/oerp/python-programs/flask-app/bitiface/venv/lib/python2.7/site-packages/oauthlib/oauth2/rfc6749/clients/base.py", line 409, in parse_request_body_response 
    self.token = parse_token_response(body, scope=scope) 
    File "/home/oerp/python-programs/flask-app/bitiface/venv/lib/python2.7/site-packages/oauthlib/oauth2/rfc6749/parameters.py", line 376, in parse_token_response 
    validate_token_parameters(params) 
    File "/home/oerp/python-programs/flask-app/bitiface/venv/lib/python2.7/site-packages/oauthlib/oauth2/rfc6749/parameters.py", line 383, in validate_token_parameters 
    raise_from_error(params.get('error'), params) 
    File "/home/oerp/python-programs/flask-app/bitiface/venv/lib/python2.7/site-packages/oauthlib/oauth2/rfc6749/errors.py", line 325, in raise_from_error 
    raise cls(**kwargs) 
InvalidClientIdError: (invalid_request) redirect_uri does not match 

它看起來像如果我跳過oath_session,那麼它實際上開始於回調和REDIRECT_URI新的會話將不匹配或類似的東西。

有誰知道可能是什麼問題?

更新

我更新燒瓶secret_key,所以就沒有secret_key錯誤消失,但第二個錯誤仍然存​​在。此錯誤:InvalidClientIdError: (invalid_request) redirect_uri does not match升起在這部分代碼:

... 
... 
bitbucket.fetch_token(
    token_url, 
    client_secret=client_secret, 
    authorization_response=request.url) 
... 
... 

我不知道這是相關的,但打印request.url,它給了我這樣的:https://127.0.0.1:5000/callback?state=[bunch_of_random_symbols]。因此,第一部分https://127.0.0.1:5000/callback與我在消費者上設置的回調URL完全相同。對我來說,它看起來實際上是匹配的。 `

P.S.提供完整的追溯。

+0

1.首先,您需要設置會話密鑰(http://flask.pocoo.org/docs/0.12/quickstart/#sessions)才能使用Flask會話。你能延續最後的回溯嗎?哪行代碼導致了這個錯誤? –

+0

@SergeyShubin查看更新後的問題。我已經回答你的問題。 – Andrius

回答

0

主要錯誤的原因是redirect_uri參數存在於授權URL中,但未在訪問令牌請求中傳遞。作爲RFC 6749描述:

redirect_uri

REQUIRED, if the "redirect_uri" parameter was included in the authorization request as described in Section 4.1.1, and their values MUST be identical.

所以你需要redirect_uri初始化回調的OAuth會話:

@app.route("/callback") 
def callback(): 
    bitbucket = OAuth2Session(
     client_id, state=session['oauth_state'], redirect_uri=redirect_uri 
    ) 

正是開發商爲什麼我們需要發送redirect_uri用於獲得訪問令牌中相當普遍的問題。 Security.Stackexchange上的This discussion可能會有幫助。

至於第一個錯誤:

RuntimeError: The session is unavailable because no secret key was set. Set the secret_key on the application to something unique and secret. 

當您嘗試保存瓶會話瓶應用程序的一些信息,但secret key沒有設置它上升。