Skip to content

Instantly share code, notes, and snippets.

@ne-sachirou
Created December 11, 2024 18:39
Show Gist options
  • Select an option

  • Save ne-sachirou/05b0fb02d91baa33cc25b48746a4d2e4 to your computer and use it in GitHub Desktop.

Select an option

Save ne-sachirou/05b0fb02d91baa33cc25b48746a4d2e4 to your computer and use it in GitHub Desktop.
デバイス フローを使用してユーザー アクセス トークンを生成する
{:deps {ring/ring-codec {:mvn/version "1.2.0"}}}
;; GitHub アプリのユーザー アクセス トークンの生成 - GitHub Docs#デバイス フローを使用してユーザー アクセス トークンを生成する https://docs.github.com/ja/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-user-access-token-for-a-github-app#using-the-device-flow-to-generate-a-user-access-token
(ns user)
(require '[babashka.http-client :as http])
(require '[ring.util.codec :as codec])
(def client-id "云々")
(defn post-device-code
""
[client-id]
(let [resp (http/post "https://github.com/login/device/code" {:form-params {:client_id client-id}})
body (-> resp :body codec/form-decode clojure.walk/keywordize-keys)]
(if (= 200 (:status resp))
{:device_code (:device_code body)
:expires_in (-> body :expires_in Integer/parseInt)
:interval (-> body :interval Integer/parseInt)
:user_code (:user_code body)
:verification_uri (:verification_uri body)}
(throw (-> resp str Exception.)))))
(defn post-access-token
""
[client-id device-code]
(let [resp (http/post "https://github.com/login/oauth/access_token"
{:form-params {:client_id client-id
:device_code device-code
:grant_type "urn:ietf:params:oauth:grant-type:device_code"}})
body (-> resp :body codec/form-decode clojure.walk/keywordize-keys)]
(if (= 200 (:status resp))
(if (-> body :error seq)
{:error (:error body)
:error_description (:error_description body)}
{:access_token (:access_token body)
:expires_in (-> body
:expires_in
Integer/parseInt
java.time.Instant/ofEpochSecond
(.atZone (java.time.ZoneId/systemDefault)))
:refresh_token (:refresh_token body)
:refresh_token_expires_in (-> body
:refresh_token_expires_in
Integer/parseInt
java.time.Instant/ofEpochSecond
(.atZone (java.time.ZoneId/systemDefault)))})
(throw (-> resp str Exception.)))))
(let [device-code-resp (post-device-code client-id)]
(println "user_code :" (:user_code device-code-resp))
(println "access to" (:verification_uri device-code-resp) "and enter the user_code")
;; (clojure.java.browse/browse (-> device-code-resp :verification_uri))
(loop [i 0]
(if (>= i (-> device-code-resp :expires_in (/ (:interval device-code-resp))))
(do (println "timeout")
(System/exit 1))
(do (-> device-code-resp :interval (* 1000) Thread/sleep)
(let [access-token-resp (post-access-token client-id (:device_code device-code-resp))]
(if (-> access-token-resp :error seq)
(recur (inc i))
(do (println "access_token :" (:access_token access-token-resp))
(println "expires_in :"
(-> access-token-resp
:expires_in
(.format java.time.format.DateTimeFormatter/ISO_ZONED_DATE_TIME))))))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment