101 lines
3.9 KiB
Clojure
101 lines
3.9 KiB
Clojure
(ns cat.moauth
|
|
(:require [cat.config :refer [env]]
|
|
[clj-http.client :as httpclient]
|
|
[slingshot.slingshot :refer [try+]]
|
|
[clojure.tools.logging :as log]
|
|
[cat.layout :refer [error-page]]))
|
|
|
|
; Inspired by https://leonid.shevtsov.me/post/oauth2-is-easy/
|
|
|
|
(defn- oauth2-params []
|
|
{:client-id (env :oauth-consumer-key)
|
|
:client-secret (env :oauth-consumer-secret)
|
|
:authorize-uri (env :authorize-uri)
|
|
:redirect-uri (str (env :app-host) "/oauth/oauth-callback")
|
|
:access-token-uri (env :access-token-uri)
|
|
;:scope "activity profile"
|
|
})
|
|
|
|
; To authorize, redirect the user to the sign in / grant page
|
|
|
|
(defn- authorize-uri
|
|
[client-params ;csrf-token
|
|
]
|
|
(str
|
|
(:authorize-uri client-params)
|
|
"?"
|
|
(httpclient/generate-query-string {:response_type "code"
|
|
:client_id (:client-id client-params)
|
|
:redirect_uri (:redirect-uri client-params)})
|
|
;"response_type=code"
|
|
;"&client_id="
|
|
;(url-encode (:client-id client-params))
|
|
;"&redirect_uri="
|
|
;(url-encode (:redirect-uri client-params))
|
|
;"&scope="
|
|
;(url-encode (:scope client-params))
|
|
;"&state="
|
|
;(url-encode csrf-token)
|
|
))
|
|
|
|
(defn authorize-api-uri
|
|
"let the user authorize access by redirecting to the signin / grant page
|
|
of the used oauth api"
|
|
[]
|
|
(authorize-uri (oauth2-params)))
|
|
|
|
(defn get-authentication-response
|
|
"Request an access token with the obtained unique code from the grant page"
|
|
[csrf-token {:keys [state code]}]
|
|
(if (or true (= csrf-token state))
|
|
(try
|
|
(do
|
|
(log/info "Requesting access token with code " code)
|
|
(let [oauth2-params (oauth2-params)
|
|
access-token (httpclient/post (:access-token-uri oauth2-params)
|
|
{:form-params {:code code
|
|
:grant_type "authorization_code"
|
|
:client_id (:client-id oauth2-params)
|
|
:client_secret (:client-secret oauth2-params)
|
|
:redirect_uri (:redirect-uri oauth2-params)}
|
|
;:basic-auth [(:client-id oauth2-params) (:client-secret oauth2-params)]
|
|
:as :json
|
|
})]
|
|
(println "Access token response:" access-token)
|
|
(:body access-token)))
|
|
(catch Exception e (log/error "Something terrible happened..." e)))
|
|
nil))
|
|
|
|
(defn get-user-info
|
|
"User info API call"
|
|
[access-token]
|
|
(let [url (str (env :user-api-uri))]
|
|
(-> (httpclient/get url {:oauth-token access-token
|
|
:as :json})
|
|
:body)
|
|
))
|
|
|
|
; Refresh token when it expires
|
|
(defn- refresh-tokens
|
|
"Request a new token pair"
|
|
[refresh-token]
|
|
(try+
|
|
(let [oauth2-params (oauth2-params)
|
|
{{access-token :access_token refresh-token :refresh_token} :body}
|
|
(httpclient/post (:access-token-uri oauth2-params)
|
|
{:form-params {:grant_type "refresh_token"
|
|
:refresh_token refresh-token}
|
|
:basic-auth [(:client-id oauth2-params) (:client-secret oauth2-params)]
|
|
:as :json})]
|
|
[access-token refresh-token])
|
|
(catch [:status 401] _ nil)))
|
|
|
|
(defn get-fresh-tokens
|
|
"Returns current token pair if they have not expired, or a refreshed token pair otherwise"
|
|
[access-token refresh-token]
|
|
(try+
|
|
(and (get-user-info access-token)
|
|
[access-token refresh-token])
|
|
(catch [:status 401] _ (refresh-tokens refresh-token))))
|
|
|