2014-12-08 4 views
2

Я хочу, чтобы подключение OpenID работало в моем маленьком проекте luminus. Я немного новичок в рабочем процессе в luminus/ring/compojure (в основном из django, flask и servlets). Я успешно перенаправляюсь в Google, поэтому я возвращаю «код» из Google, но затем мне нужно сделать еще один запрос в Google до входа в систему пользователя, и для этого вызова требуется другой обратный вызов, в который пользователь не участвует, поэтому мне нужно поставить запрос пользователя на удержание как обещание, но я не уверен, как эта часть работает в compojure.SOLVED: реализация oauth2 в compojure, как мне ждать второй обратный вызов oauth2, прежде чем отвечать на запрос пользователя?

; this is my code that redirects them to Google, where they accept 
(defn login [params] 
    (let [google-oauth2-client-id (System/getenv "GOOGLE_OAUTH2_CLIENT_ID") 
     base-url "https://accounts.google.com/o/oauth2/auth" 
     args {"client_id" google-oauth2-client-id 
       "response_type" "code" 
       "scope" "openid email" 
       "redirect_uri" "http://localhost:3000/oauth2Callback" 
       "state" "anti-forgery here"}] 

    (assert google-oauth2-client-id "can't find GOOGLE_OAUTH2_CLIENT_ID in environment") 

    (redirect (str base-url "?" (make-query-string args))) 
    ) 
) 

; this is my code handling Google's first response 
(defn oauth2-callback [params] 
    ; params has the code to send to Google 

    ; here I should send another request to google that comes back to another callback like oauth2-token-callback that processes the request to the user in the current context 

    (redirect "/youreloggedin") 
) 

К концу этого метода я должен представляемого пользователю сообщение о том, что они вошли в систему, но мне нужно ждать, пока запрос не возвращается. Как этот рабочий процесс обрабатывается в luminus?

Спасибо. Я не понимал, что могу просто игнорировать параметр обратного вызова.

(client/post "https://www.googleapis.com/oauth2/v3/token" 
       {:headers {"X-Api-Version" "2"} 
       :content-type :application/x-www-form-urlencoded 
       :form-params {:code (params :code) 
           :client_id (System/getenv "GOOGLE_OAUTH2_CLIENT_ID") 
           :client_secret (System/getenv "GOOGLE_OAUTH2_CLIENT_SECRET") 
           :redirect_uri "http://localhost:3000/oauth2Callback" ; ignored 
           :grant_type "authorization_code" 
           } 
       :as :auto ; decode the body straight to hash (if possible) 
      }) 

ответ

1

На основании документации OAuth2 от Google для веб-серверов here поток состоит из следующих этапов:

  1. Ваше приложение перенаправляет браузер к URL Google; URL содержит параметры запроса, указывающие тип запрашиваемого доступа.
  2. Результатом является код авторизации, который Google возвращает в ваше приложение в строке запроса.
  3. После получения кода авторизации ваше приложение может обмениваться кодом (вместе с идентификатором клиента и секретом клиента) для токена доступа и в некоторых случаях токена обновления.

Если я правильно понял ваш вопрос, шаг 3 не обязательно включает обратный вызов на ваш сервер, вы можете просто выполнить запрос в Google с помощью HTTP-клиента. Я недавно внедренная oauth2 для GitHub в этом project, шаг 3 реализуется в этом function:

(defn callback 
    "Handles the callback from GitHub OAuth flow." 
    [code] 
    (let [params {:form-params {:client_id client-id 
           :client_secret client-secret 
           :code code}} 
     {:keys [body]} (client/post access-token-url params) ;; This is doing the POST 
                  ;; request to GitHub. 
     token ((qs-map body) "access_token")]    ;; Getting the token from 
                  ;; the response here. 
    {:status 302 
    :headers {"location" "/repos" 
       "set-cookie" (str "token=" token ";Path=/")}})) 

Я использовал clj-http как клиент HTTP, но любой другой будет делать.