1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
(ns mulk.benki.auth
(:refer-clojure)
(:use [clojure core repl pprint]
[hiccup core page-helpers]
[mulk.benki config util db]
[clojure.core.match
:only [match]]
[noir core]
[clojure.java.jdbc :only [transaction do-commands]])
(:require [noir.session :as session]
[noir.response :as response]
[noir.request :as request]
[clojure.java.jdbc :as sql]
[com.twinql.clojure.http :as http])
(:import [org.openid4java.consumer ConsumerManager]
[org.openid4java.message ParameterList]))
(defonce manager (ConsumerManager.))
(defn return-from-openid-provider []
(let [parlist (ParameterList. (:query-params (request/ring-request)))
discovered (session/get :discovered)
;; Does the following work for POST requests?
request-uri (str (resolve-uri "/login/return")
(let [query-string (:query-string (request/ring-request))]
(if query-string
(str "?" query-string)
"")))
verification (.verify manager request-uri parlist discovered)
id (.getVerifiedId verification)]
(if id
(with-dbt
(let [openid (first (query "SELECT * FROM openids WHERE openid = ?"
(.getIdentifier id)))
user-id (if openid
(:user openid)
nil)
user (first (if user-id
(query "SELECT * FROM users WHERE id = ?" user-id)
nil))]
(if user-id
(do (session/put! :user user-id)
(if-let [return-uri (session/flash-get)]
(redirect return-uri)
(layout {} "Authenticated!" [:p "Welcome back, " (:first_name user) "!"])))
(layout "Authentication Failed"
[:p "Did not recognize OpenID."]
[:p "Your OpenID is: " [:strong (.getIdentifier id)]]))))
(layout "Authentication Failed" [:p "OpenID authentication failed."]))))
(defpage [:post "/login/browserid/verify"] {assertion :assertion}
;; NB. Can implement this ourselves if we want.
(let [reply (http/post "https://browserid.org/verify"
:query {:assertion assertion
:audience (:base-uri @benki-config)}
:as :json)
result (:content reply)
status (:status result)
email (:email result)]
(if (= (:status result) "okay")
(with-dbt
(let [record (first (query "SELECT * FROM user_email_addresses WHERE email = ?" email))
user-id (and record (:user record))]
(if user-id
(let [return-uri (session/flash-get)]
(session/put! :user user-id)
(response/json {:email email, :returnURI return-uri}))
{:status 422,
:headers {"Content-Type" "text/plain"},
:body "I couldn't find you in the database."})))
{:status 400,
:headers {"Content-Type" "text/plain"},
:body "Your BrowserID request was crooked."})))
(defpage [:post "/login/return"] []
(return-from-openid-provider))
(defpage "/login/return" []
(return-from-openid-provider))
(defpage "/login/authenticate" {openid :openid_identifier}
(let [discoveries (.discover manager openid)
discovered (.associate manager discoveries)
authreq (.authenticate manager discovered (resolve-uri "/login/return"))]
(session/put! :discovered discovered)
(redirect (.getDestinationUrl authreq true))))
(def login-page-layout
{:head
(list
[:link {:type "text/css", :rel "stylesheet", :href (resolve-uri "/3rdparty/openid-selector/css/openid.css")}])
:bottom
(list
[:script {:type "text/javascript", :src (resolve-uri "/3rdparty/openid-selector/js/openid-jquery.js")}]
[:script {:type "text/javascript", :src (resolve-uri "/3rdparty/openid-selector/js/openid-en.js")}]
[:script {:type "text/javascript", :src (resolve-uri "/js/openid-login.js")}]
)})
(defpage "/login" []
(session/flash-put! (or (session/flash-get)
(get-in (request/ring-request) [:headers "referer"])))
(layout login-page-layout "Benki Login"
[:div#browserid-box
[:h2 "BrowserID login"]
[:a#browserid {:href "#"}
[:img {:src (resolve-uri "/3rdparty/browserid/sign_in_orange.png")
:alt "Sign in using BrowserID"}]]]
[:div#openid-login-panel
[:h2 "OpenID login"]
[:form {:action (resolve-uri "/login/authenticate"),
:method "GET"
:id "openid_form"}
[:div {:id "openid_choice"}
[:p "Please select your OpenID provider:"]
[:div {:id "openid_btns"}]]
[:div {:id "openid_input_area"}
[:input {:type "text", :name "openid_identifier", :id "openid_identifier"}]
[:input {:type "submit"}]]]]))
|