2011-10-18 39 views
10

我想設置一個休息api與oauth 2.0提供程序進行身份驗證。我使用python。 是否有任何庫設置oauth 2.0提供程序編碼在運行在應用程序引擎上的python? 謝謝。谷歌應用程序引擎oauth2提供者

回答

2

您是否檢出了OAuth for Python文章信息?它表示這是爲「此參考描述如何將OAuth與Python應用程序一起用作服務提供者。」

+0

! – neo

+0

然後查看[python-oauth2](https://github.com/simplegeo/python-oauth2)瞭解Python中的完整OAuth實現。 –

+1

我認爲,儘管名稱可以用於創建只有oauth 1.0提供商 – neo

22

OAuth2支持Python和Java App Engine運行時內置。

在Python所有你需要的是:

from google.appengine.api import oauth 

# Note, unlike in the Android app below, there's no 'oauth2:' prefix here 
SCOPE = 'https://www.googleapis.com/auth/userinfo.email' 

# magic happens here 
user = oauth.get_current_user(SCOPE) 

在Java中,你可以使用:

OAuthService oauth = OAuthServiceFactory.getOAuthService(); 

// Note, unlike in the Android app below, there's no 'oauth2:' prefix here 
String SCOPE = "https://www.googleapis.com/auth/userinfo.email"; 

// magic happens here 
User user = oauth.getCurrentUser(SCOPE); 

下面是完整的Python 2.7的處理程序,讓您以驗證用戶:

from google.appengine.api import oauth 
import logging 
import traceback 
import webapp2 


class MainHandler(webapp2.RequestHandler): 

    def post(self): 
    self.response.headers['Content-Type'] = 'text/plain' 
    self.response.write('Hi there!\n') 

    # Note, unlike in the Android app below, there's no 'oauth2:' prefix here 
    scope = 'https://www.googleapis.com/auth/userinfo.email' 
    try: 
     self.response.write('\noauth.get_current_user(%s)' % repr(scope)) 

     # validates audience of the OAuth2 access token 
     allowed_clients = ['407408718192.apps.googleusercontent.com'] # list your client ids here 
     token_audience = oauth.get_client_id(scope) 
     if token_audience not in allowed_clients: 
     raise oauth.OAuthRequestError('audience of token \'%s\' is not in allowed list (%s)' % (token_audience, allowed_clients))   

     # gets user object for the user represented by the oauth token 
     user = oauth.get_current_user(scope) 
     self.response.write(' = %s\n' % user) 
     self.response.write('- auth_domain = %s\n' % user.auth_domain()) 
     self.response.write('- email  = %s\n' % user.email()) 
     self.response.write('- nickname = %s\n' % user.nickname()) 
     self.response.write('- user_id  = %s\n' % user.user_id()) 
    except oauth.OAuthRequestError, e: 
     self.response.set_status(401) 
     self.response.write(' -> %s %s\n' % (e.__class__.__name__, e.message)) 
     logging.warn(traceback.format_exc()) 


app = webapp2.WSGIApplication([ 
    ('/.*', MainHandler) 
], debug=True) 

該app.yaml是微不足道的

application: your-app-id 
version: 1 
runtime: python27 
api_version: 1 
threadsafe: true 

handlers: 
- url: /favicon\.ico 
    static_files: favicon.ico 
    upload: favicon\.ico 

- url: .* 
    script: main.app 

請注意,客戶端應該在Authorization: Bearer HTTP請求標頭中發送OAuth2令牌,例如,

Authorization: Bearer ya29XAHES6ZT4w72FecXjZu4ZWskTSX3x3OqYxUSTIrA2IfxDDPpI 

如果你碰巧要建立一個Android應用程序,你可以很容易地使用AccountManager界面生成這些令牌:

AccountManager accountManager = AccountManager.get(this); 
Account[] accounts = accountManager.getAccountsByType("com.google"); 

// TODO: Allow the user to specify which account to authenticate with 
for (Account account : accounts) { 
    Log.i(TAG, "- account.name = " + account.name); 
} 

// Note the "oauth2:" prefix here 
String authTokenType = "oauth2:https://www.googleapis.com/auth/userinfo.email"; 

// Note: AccountManager will cache these token, even after they've expired. 
// TODO: Invalidate expired tokens, either after auth fails, or preemptively via: 
// accountManager.invalidateAuthToken(accounts[0].type, token); 

accountManager.getAuthToken(accounts[0], authTokenType, null, this, 
    new AccountManagerCallback<Bundle>() { 
     @Override 
     public void run(AccountManagerFuture<Bundle> future) { 
     try { 
      String token = future.getResult().getString(AccountManager.KEY_AUTHTOKEN); 
      Log.i(TAG, "Got KEY_AUTHTOKEN: " + token); 
      // Don't forget HTTP Header "Authorization: Bearer <token>" 
      callAppEngineRestApi(token); // <---- Your code here 
     } catch (OperationCanceledException e) { 
      Log.i(TAG, "The user has denied you access to the API"); 
     } catch (Exception e) { 
      Log.i(TAG, "Exception: ", e); 
     } 
     } 
    }, null); 

如果你想看到的一切放在一起,隨時結賬這些項目的完整源:

+0

你確定嗎? Afaik Gae只支持Oauth 1.0a – systempuntoout

+0

我測試了你的代碼,但它不工作產生 - 例外: - 我使用python 2.5。 – Chameleon

+0

圍繞Google和StackOverflow展開了一番研究。這是我找到的具有良好工作代碼的唯一答案。 (請參閱提供的URL以獲取完整示例)。 也適用於Java,因此問題標題可能會誤導Java用戶。 – Guy

0

所以我在這裏增加它的人在這個片段中掙扎,我不能在上面的回答發表評論:

# magic happens here 
user = oauth.get_current_user(SCOPE) 

這如果您使用服務帳戶(至今爲止,我認爲也是Google用戶令牌),因此令牌長度在AE庫中會導致問題,因此已在AppEngine上停留了一個月。 Google告訴我他們不可能很快修復它。

這是對我的作品,此刻的唯一的事情:使用谷歌認證不是我的服務,這讓我完全認證依賴於谷歌

token = self.request.headers['Authorization'].split(' ')[1] 
    url = 'https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=' + token 
    oauth_response = urlfetch.fetch(url) 
    if oauth_response.status_code != 200: 
     raise Exception('Unable to authorise: {}/{}'.format(oauth_response.status_code, oauth_response.content)) 
    token_response = json.loads(oauth_response.content) 
    email = token_response['email'] 
+0

這是做什麼用的?它背後的邏輯是什麼? – Praxiteles

+0

它使用谷歌休息api'解碼'不記名令牌,從響應中提取電子郵件地址。 – KevH