Skip to content

Instantly share code, notes, and snippets.

@jwhitlark
Forked from arohner/google-api.clj
Created January 31, 2019 19:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jwhitlark/ed7be1c40d843cedde1a443d3d98deef to your computer and use it in GitHub Desktop.
Save jwhitlark/ed7be1c40d843cedde1a443d3d98deef to your computer and use it in GitHub Desktop.
Clojure example of accessing google APIs directly
(ns example.api.google
(:require [cemerick.url :as url]
[cheshire.core :as json]
[clj-jwt.core :as jwt]
[clj-jwt.key :as key]
[clj-time.core :as time]
[clj-http.client :as http]
[clojure.string :as str])
(:import java.io.StringReader))
;;; Example code for calling Google apis using a service account.
(defn load-creds
"Takes a path to a service account .json credentials file"
[secrets-json-path]
(-> secrets-json-path slurp (json/parse-string keyword)))
;; list of API scopes requested, e.g. https://developers.google.com/admin-sdk/directory/v1/guides/authorizing
(def scopes ["https://www.googleapis.com/auth/admin.directory.user"
"https://www.googleapis.com/auth/admin.directory.group"])
(defn create-claim [creds & [{:keys [sub] :as opts}]]
(let [claim (merge {:iss (:client_email creds)
:scope (str/join " " scopes)
:aud "https://www.googleapis.com/oauth2/v4/token"
:exp (-> 1 time/hours time/from-now)
:iat (time/now)}
(when sub
;; when using the Admin API, delegating access, :sub may be needed
{:sub sub}))]
(-> claim jwt/jwt (jwt/sign :RS256 (-> creds :private_key (#(StringReader. %)) (#(key/pem->private-key % nil)))) (jwt/to-str))))
(defn request-token [creds & [{:keys [sub] :as opts}]]
(let [claim (create-claim creds opts)
resp (http/post "https://www.googleapis.com/oauth2/v4/token" {:form-params {:grant_type "urn:ietf:params:oauth:grant-type:jwt-bearer"
:assertion claim}
:as :json})]
(when (= 200 (-> resp :status))
(-> resp :body :access_token))))
;; Call request-token to make an API call to google to create a new access token, using creds. Access-tokens are valid for 1 hour after creating. Pass the received token to API calls.
(defn api-req [{:keys [] :as request} token]
(http/request (-> request
(assoc-in [:headers "Authorization"] (str "Bearer " token))
(assoc :as :json))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment