Реализация oauth2 в compojure, как мне ждать второго обратного вызова oauth2, прежде чем ответить на запрос пользователя?
Я бы хотел, чтобы OpenID connect работал в моем маленьком проекте luminus. Я немного новичок в рабочем процессе в luminus / ring / compojure (в основном от django, flask и сервлетов). Я успешно перенаправлен в Google, поэтому я получил "код" от Google, но затем мне нужно сделать еще один запрос в Google, прежде чем войти в систему пользователя, и этот вызов требует другого обратного вызова, в котором пользователь не участвует, поэтому мне нужно приостановить запрос пользователя, как обещание, но я не уверен, как эта часть работает в compojure.
; 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 ответ
Основываясь на документации по Google OAuth2 для веб-серверов, этот процесс состоит из следующих шагов:
- Ваше приложение перенаправляет браузер на URL Google; URL включает параметры запроса, которые указывают тип запрашиваемого доступа.
- В результате получается код авторизации, который Google возвращает вашему приложению в строке запроса.
- После получения кода авторизации ваше приложение может обменять код (вместе с идентификатором клиента и секретом клиента) на токен доступа и, в некоторых случаях, токен обновления.
Если я правильно понял ваш вопрос, на шаге 3 не обязательно будет обратный вызов на ваш сервер, вы можете просто выполнить запрос в Google с помощью HTTP-клиента. Я недавно внедрил OAuth2 для GitHub в этом проекте, шаг 3 реализован в этой функции:
(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-клиента, но подойдет любой другой.