Official Clojure SDK for Authdog authentication and user management platform.
Add the following dependency to your project.clj:
[authdog "0.1.0"]Add the following dependency to your deps.edn:
{authdog {:mvn/version "0.1.0"}}- Clojure 1.11 or higher
- clj-http HTTP client
- Cheshire JSON library
(require '[authdog.core :as authdog]
'[authdog.exceptions :as ex])
;; Initialize the client
(def client (authdog/make-client "https://api.authdog.com"))
;; Get user information
(try
(let [user-info (authdog/get-user-info client "your-access-token")]
(println "User:" (:display-name (:user user-info))))
(catch clojure.lang.ExceptionInfo e
(cond
(ex/authentication-error? e)
(println "Authentication failed:" (.getMessage e))
(ex/api-error? e)
(println "API error:" (.getMessage e)))))(def client (authdog/make-client "https://api.authdog.com"))(def client (authdog/make-client "https://api.authdog.com"
{:api-key "your-api-key"}))(def client (authdog/make-client "https://api.authdog.com"
{:api-key "your-api-key"
:timeout 30000}))(make-client base-url)
(make-client base-url options)Create a new Authdog client.
Parameters:
base-url: The base URL of the Authdog APIoptions: Optional configuration map with keys::api-key- Optional API key for authentication:timeout- Request timeout in milliseconds (default: 10000)
(get-user-info client access-token)Get user information using an access token.
Parameters:
client: The Authdog clientaccess-token: The access token for authentication
Returns: Map containing user information
Throws:
clojure.lang.ExceptionInfowith:authentication-errortype when authentication failsclojure.lang.ExceptionInfowith:api-errortype when API request fails
{:meta {:code 200
:message "Success"}
:session {:remaining-seconds 56229}
:user {:id "user-id"
:external-id "external-id"
:user-name "username"
:display-name "Display Name"
:nick-name nil
:profile-url nil
:title nil
:user-type nil
:preferred-language nil
:locale "en"
:timezone nil
:active true
:names {:id "name-id"
:formatted nil
:family-name "Last"
:given-name "First"
:middle-name nil
:honorific-prefix nil
:honorific-suffix nil}
:photos [{:id "photo-id"
:value "https://example.com/photo.jpg"
:type "photo"}]
:phone-numbers []
:addresses []
:emails [{:id "email-id"
:value "email@example.com"
:type nil}]
:verifications [{:id "verification-id"
:email "email@example.com"
:verified true
:created-at "2024-01-01T00:00:00Z"
:updated-at "2024-01-01T00:00:00Z"}]
:provider "google-oauth20"
:created-at "2024-01-01T00:00:00Z"
:updated-at "2024-01-01T00:00:00Z"
:environment-id "env-id"}}The SDK provides structured error handling with specific exception types:
(try
(authdog/get-user-info client "invalid-token")
(catch clojure.lang.ExceptionInfo e
(when (ex/authentication-error? e)
(println "Authentication failed:" (.getMessage e)))))(try
(authdog/get-user-info client "valid-token")
(catch clojure.lang.ExceptionInfo e
(when (ex/api-error? e)
(println "API error:" (.getMessage e)))))(try
(authdog/get-user-info client "token")
(catch clojure.lang.ExceptionInfo e
(when (ex/authdog-error? e)
(println "Authdog error:" (.getMessage e)))))(require '[authdog.core :as authdog]
'[authdog.exceptions :as ex])
(defn main []
(let [client (authdog/make-client "https://api.authdog.com")]
(try
(let [user-info (authdog/get-user-info client "your-access-token")
user (:user user-info)]
(println "User ID:" (:id user))
(println "Display Name:" (:display-name user))
(println "Provider:" (:provider user))
(when-let [email (first (:emails user))]
(println "Email:" (:value email))))
(catch clojure.lang.ExceptionInfo e
(cond
(ex/authentication-error? e)
(println "Authentication failed:" (.getMessage e))
(ex/api-error? e)
(println "API error:" (.getMessage e)))))))
(main)(defn get-user-with-error-handling [client access-token]
(try
(authdog/get-user-info client access-token)
(catch clojure.lang.ExceptionInfo e
(cond
(ex/authentication-error? e)
(do (println "Authentication failed:" (.getMessage e))
nil)
(ex/api-error? e)
(do (println "API error:" (.getMessage e))
nil)))))(defrecord UserService [client])
(defn make-user-service [base-url & {:keys [api-key timeout]}]
(->UserService (authdog/make-client base-url
{:api-key api-key
:timeout timeout})))
(defn get-user-data [service access-token]
(try
(let [user-info (authdog/get-user-info (:client service) access-token)
user (:user user-info)]
{:id (:id user)
:display-name (:display-name user)
:email (when-let [email (first (:emails user))]
(:value email))
:provider (:provider user)
:active (:active user)})
(catch clojure.lang.ExceptionInfo e
(cond
(ex/authentication-error? e)
(throw (Exception. (str "Authentication failed: " (.getMessage e))))
(ex/api-error? e)
(throw (Exception. (str "API error: " (.getMessage e))))))))
;; Usage
(def service (make-user-service "https://api.authdog.com"))
(def user-data (get-user-data service "your-access-token"))(require '[ring.util.response :as response]
'[compojure.core :refer [defroutes GET]]
'[authdog.core :as authdog]
'[authdog.exceptions :as ex])
(def authdog-client (authdog/make-client "https://api.authdog.com"))
(defn user-info-handler [request]
(let [access-token (get-in request [:params :access_token])]
(try
(let [user-info (authdog/get-user-info authdog-client access-token)
user (:user user-info)]
(response/response {:id (:id user)
:display-name (:display-name user)
:email (when-let [email (first (:emails user))]
(:value email))
:provider (:provider user)}))
(catch clojure.lang.ExceptionInfo e
(cond
(ex/authentication-error? e)
(-> (response/response {:error "Authentication failed"})
(response/status 401))
(ex/api-error? e)
(-> (response/response {:error (.getMessage e)})
(response/status 400)))))))
(defroutes app
(GET "/user/info" request (user-info-handler request)))(require '[compojure.api.sweet :refer [defapi GET]]
'[ring.util.http-response :refer [ok unauthorized bad-request]]
'[authdog.core :as authdog]
'[authdog.exceptions :as ex])
(defapi app
(GET "/user/info" []
:query-params [access-token :- String]
(try
(let [client (authdog/make-client "https://api.authdog.com")
user-info (authdog/get-user-info client access-token)
user (:user user-info)]
(ok {:id (:id user)
:display-name (:display-name user)
:email (when-let [email (first (:emails user))]
(:value email))
:provider (:provider user)}))
(catch clojure.lang.ExceptionInfo e
(cond
(ex/authentication-error? e)
(unauthorized {:error "Authentication failed"})
(ex/api-error? e)
(bad-request {:error (.getMessage e)}))))))(require '[io.pedestal.http :as http]
'[io.pedestal.http.route :as route]
'[authdog.core :as authdog]
'[authdog.exceptions :as ex])
(defn user-info-interceptor [request]
(let [access-token (get-in request [:query-params :access_token])]
(try
(let [client (authdog/make-client "https://api.authdog.com")
user-info (authdog/get-user-info client access-token)
user (:user user-info)]
{:status 200
:body {:id (:id user)
:display-name (:display-name user)
:email (when-let [email (first (:emails user))]
(:value email))
:provider (:provider user)}})
(catch clojure.lang.ExceptionInfo e
(cond
(ex/authentication-error? e)
{:status 401
:body {:error "Authentication failed"}}
(ex/api-error? e)
{:status 400
:body {:error (.getMessage e)}})))))
(def routes
(route/expand-routes
#{["/user/info" :get user-info-interceptor :route-name :user-info]}))
(def service-map
{::http/routes routes
::http/port 8080})
(defn start-server []
(http/start (http/create-server service-map)))(require '[re-frame.core :as rf]
'[authdog.core :as authdog]
'[authdog.exceptions :as ex])
(def authdog-client (authdog/make-client "https://api.authdog.com"))
(rf/reg-fx
:authdog/get-user-info
(fn [[access-token success-event error-event]]
(-> (future (authdog/get-user-info authdog-client access-token))
(deref 10000 nil)
(cond
(ex/authdog-error? %) (rf/dispatch [error-event (.getMessage %)])
:else (rf/dispatch [success-event %])))))
(rf/reg-event-fx
:authdog/load-user-info
(fn [_ [_ access-token]]
{:fx [[:authdog/get-user-info [access-token :authdog/user-info-success :authdog/user-info-error]]]}))
(rf/reg-event-db
:authdog/user-info-success
(fn [db [_ user-info]]
(assoc db :user-info user-info)))
(rf/reg-event-db
:authdog/user-info-error
(fn [db [_ error-message]]
(assoc db :authdog-error error-message)))lein compilelein testlein jarlein install- Clojure 1.11+
- Leiningen 2.9+
- clj-http 3.12.3+
- Cheshire 5.11.0+
- Midje (for testing)
- Follow Clojure Style Guide
- Use
cljfmtfor formatting - Use meaningful function and variable names
- Use
defnfor functions - Use
try-catchfor error handling - Prefer
letoverdeffor local bindings - Use
->and->>for threading
# Run all tests
lein test
# Run tests with Midje
lein midje
# Run specific test
lein test authdog.core-testMIT License - see LICENSE for details.