Examples
The friend-oauth2 project includes the following examples:
Configuration
The examples make use of the following environment variables:
OAUTH2_CLIENT_ID
OAUTH2_CLIENT_SECRET
OAUTH2_CALLBACK_URL
Running
Once the environment variables are set, you will be ready to run the examples. There are two sets of examples, one set for each type of configuration support friend-oauth2
provides (see configuration documentation for more details).
Record-based Configuration
The examples configured using the new records support can be run with the following lein
aliases:
lein appdotnet
lein facebook
lein github
lein google
Note that, under the hood, the record-based configuration is backwards-compatible with the legacy configuration.
Legacy Configuration
The examples configured using the original configuration mechanism can be run with the following lein
aliases:
lein legacy-appdotnet
lein legacy-facebook
lein legacy-github
lein legacy-google
Source Code
We keep the example source code as part of the code in this repository:
However, we also recognize that it’s nice to see an example in the documentation itself, so we’ll take on the burden of maintaining the following text in the effort to provide a good docs experience for you :-)
Here’s the Google friend-oauth2
example, runable from the commandline (e.g., with lein
):
(ns friend-oauth2.examples.google
(:require [cemerick.friend :as friend]
[cemerick.friend.workflows :as workflows]
[cemerick.friend.credentials :as creds]
[clojure.tools.logging :as log]
[clojusc.twig :as logger]
[compojure.core :as compojure :refer [GET ANY defroutes]]
[friend-oauth2.service.google :as google]
[friend-oauth2.util :as util]
[org.httpkit.server :as server]
[ring.util.response :as response]
[ring.middleware.defaults :as ring-defaults])
(:gen-class))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Mini Webapp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn html
[content]
(-> content
(response/response)
(response/header "Content-Type" "text/html")))
(def index-content
(str "<a href=\"/admin\">Admin Pages</a><br />"
"<a href=\"/authlink\">Authorized page</a><br />"
"<a href=\"/authlink2\">Authorized page 2</a><br />"
"<a href=\"/status\">Status</a><br />"
"<a href=\"/logout\">Log out</a>"))
(defn get-status-content
[count session]
(str "<p>We've hit the session page "
count
" times.</p><p>The current session: "
session
"</p>"))
(defn render-index-page
[req]
(html index-content))
(defn render-status-page
[req]
(let [count (:count (:session req) 0)
session (assoc (:session req) :count (inc count))]
(-> (get-status-content count session)
(html)
(assoc :session session))))
(defroutes app-routes
(GET "/" req
(render-index-page req))
(GET "/status" req
(render-status-page req))
(GET "/authlink" req
(friend/authorize
#{::user}
(html "Authorized page.")))
(GET "/authlink2" req
(friend/authorize
#{::user}
(html "Authorized page 2.")))
(GET "/admin" req
(friend/authorize
#{::admin}
(html "Only admins can see this page.")))
(friend/logout (ANY "/logout" req (response/redirect "/"))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; OAuth2 Configuration and Integration ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn credential-fn
[token]
;;lookup token in DB or whatever to fetch appropriate :roles
{:identity token :roles #{::user}})
(def workflow
(google/workflow
{:config {:scope "email"}
:access-token-parsefn util/get-access-token-from-params
:credential-fn credential-fn}))
(def auth-opts
{:allow-anon? true
:workflows [workflow]})
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; App Server ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def app
(-> app-routes
(friend/authenticate auth-opts)
(ring-defaults/wrap-defaults ring-defaults/site-defaults)))
(defn -main
[& args]
(logger/set-level! '[ring friend friend-oauth2] :info)
(log/info "Starting example server using Google OAuth2 ...")
(server/run-server app {:port 8999}))