Skip to content

Commit

Permalink
Implement client-side authentication.
Browse files Browse the repository at this point in the history
  • Loading branch information
codonnell committed Mar 15, 2020
1 parent 269b426 commit 2ca04e7
Show file tree
Hide file tree
Showing 8 changed files with 460 additions and 7 deletions.
2 changes: 2 additions & 0 deletions deps.edn
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
:aliases {:dev {:extra-paths ["dev"]
:jvm-opts ["-Dtrace"]
:extra-deps {org.clojure/clojurescript {:mvn/version "1.10.597"}
org.clojure/core.async {:mvn/version "1.0.567"}
com.wsscode/async {:mvn/version "1.0.2"}
thheller/shadow-cljs {:mvn/version "2.8.83"}
fulcrologic/fulcro-inspect {:mvn/version "2.2.5"}
binaryage/devtools {:mvn/version "0.9.10"}}}}}
367 changes: 367 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
"description": "",
"private": true,
"devDependencies": {
"@auth0/auth0-spa-js": "^1.6.4",
"minimist": "^1.2.2",
"react": "^16.13.0",
"react-dom": "^16.13.0",
"shadow-cljs": "^2.8.83",
"minimist": "^1.2.2"
"semantic-ui-react": "^0.88.2",
"shadow-cljs": "^2.8.83"
},
"author": "Chris O'Donnell",
"license": "MIT"
Expand Down
1 change: 1 addition & 0 deletions resources/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<title>My Gift List Rocks</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css" />
</head>
<body>
<div id="app"></div>
Expand Down
6 changes: 6 additions & 0 deletions shadow-cljs.edn
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
:modules {:main {:entries [rocks.mygiftlist.client]
:init-fn rocks.mygiftlist.client/init}}

:closure-defines
{rocks.mygiftlist.config/AUTH0_CLIENT_ID "heIlMgUZmvjI3muqPO3Ua5F5VpLgTpM3"
rocks.mygiftlist.config/AUTH0_DOMAIN "mygiftlist-blog.auth0.com"
rocks.mygiftlist.config/AUTH0_AUDIENCE "https://blog.mygiftlist.rocks"
rocks.mygiftlist.config/AUTH0_CONNECTION "Username-Password-Authentication"}

:devtools {:watch-dir "resources/public"
:after-load rocks.mygiftlist.client/refresh
:preloads [com.fulcrologic.fulcro.inspect.preload
Expand Down
35 changes: 35 additions & 0 deletions src/rocks/mygiftlist/authentication.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
(ns rocks.mygiftlist.authentication
(:require ["@auth0/auth0-spa-js" :as create-auth0-client]
[com.wsscode.async.async-cljs :refer [go-promise <!p]]
[rocks.mygiftlist.config :as config]))

(defonce auth0-client (atom nil))

(defn create-auth0-client! []
(go-promise
(reset! auth0-client
(<!p (create-auth0-client
#js {:domain config/AUTH0_DOMAIN
:client_id config/AUTH0_CLIENT_ID
:audience config/AUTH0_AUDIENCE
:connection config/AUTH0_CONNECTION})))))

(defn is-authenticated? []
(go-promise (<!p (.isAuthenticated @auth0-client))))

(defn login []
(.loginWithRedirect @auth0-client
#js {:redirect_uri (.. js/window -location -origin)}))

(defn handle-redirect-callback []
(go-promise (<!p (.handleRedirectCallback @auth0-client))))

(defn logout []
(.logout @auth0-client
#js {:returnTo (.. js/window -location -origin)}))

(defn get-access-token []
(go-promise (<!p (.getTokenSilently @auth0-client))))

(defn get-user-info []
(go-promise (<!p (.getUser @auth0-client))))
44 changes: 39 additions & 5 deletions src/rocks/mygiftlist/client.cljs
Original file line number Diff line number Diff line change
@@ -1,20 +1,54 @@
(ns rocks.mygiftlist.client
(:require [rocks.mygiftlist.application :refer [SPA]]
[rocks.mygiftlist.authentication :as auth]
[com.fulcrologic.fulcro.application :as app]
[com.fulcrologic.fulcro.components :as comp :refer [defsc]]
[com.fulcrologic.fulcro.dom :as dom]
[com.fulcrologic.fulcro.mutations :refer [defmutation]]
[clojure.core.async :refer [go <!]]
[clojure.string :as str]
[taoensso.timbre :as log]))

(defsc Root [this _]
{:query []
:initial-state {}}
(defsc CurrentUser [this {:user/keys [id email]
:ui/keys [loading] :as user}]
{:query [:user/id :user/email :ui/loading]
:ident (fn [] [:component/id :current-user])
:initial-state {:ui/loading true}}
(cond
loading (dom/button :.ui.loading.primary.button)
(and id email) (dom/button :.ui.primary.button
{:onClick #(auth/logout)}
"Logout")
:else (dom/button :.ui.primary.button
{:onClick #(auth/login)}
"Login/Signup")))

(def ui-current-user (comp/factory CurrentUser))

(defsc Root [this {:root/keys [current-user]}]
{:query [{:root/current-user (comp/get-query CurrentUser)}]
:initial-state {:root/current-user {}}}
(dom/div {}
"Hello World"))
(dom/div {} "Hello World")
(ui-current-user current-user)))

(defmutation set-current-user [user]
(action [{:keys [state]}]
(swap! state assoc-in [:component/id :current-user] (assoc user :ui/loading false))))

(defn ^:export refresh []
(log/info "Hot code reload...")
(app/mount! SPA Root "app"))

(defn ^:export init []
(log/info "Application starting...")
(app/mount! SPA Root "app"))
(app/mount! SPA Root "app")
(go
(<! (auth/create-auth0-client!))
(when (str/includes? (.. js/window -location -search) "code=")
(<! (auth/handle-redirect-callback))
(.replaceState js/window.history #js {} js/document.title js/window.location.pathname))
(if-let [authenticated (<! (auth/is-authenticated?))]
(let [{:strs [sub email]} (js->clj (<! (auth/get-user-info)))]
(comp/transact! SPA [(set-current-user {:user/id sub :user/email email})]))
(comp/transact! SPA [(set-current-user {})]))))
6 changes: 6 additions & 0 deletions src/rocks/mygiftlist/config.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(ns rocks.mygiftlist.config)

(goog-define AUTH0_DOMAIN "")
(goog-define AUTH0_CLIENT_ID "")
(goog-define AUTH0_AUDIENCE "")
(goog-define AUTH0_CONNECTION "")

0 comments on commit 2ca04e7

Please sign in to comment.