Using the Noir session doesn't seem to be the right thing to do. I should be using the Ring session, but I'm having a hard time getting my head round it. @yogthos is too bloody clever!
This commit is contained in:
parent
88468461fd
commit
4e296537c4
52 changed files with 465 additions and 114 deletions
|
|
@ -5,6 +5,7 @@
|
|||
[compojure.core :refer [routes wrap-routes]]
|
||||
[compojure.route :as route]
|
||||
[mount.core :as mount]
|
||||
[noir.session :as session]
|
||||
[youyesyet.config :refer [env]]
|
||||
[youyesyet.layout :refer [error-page]]
|
||||
[youyesyet.middleware :as middleware]
|
||||
|
|
@ -73,7 +74,7 @@
|
|||
(-> #'auto-selmer-routes
|
||||
(wrap-routes middleware/wrap-csrf)
|
||||
(wrap-routes middleware/wrap-formats))
|
||||
#'oauth-routes
|
||||
'oauth-routes
|
||||
#'authenticated-routes
|
||||
(route/not-found
|
||||
(:body
|
||||
|
|
|
|||
|
|
@ -1,35 +1,101 @@
|
|||
(ns youyesyet.oauth
|
||||
(ns ^{:doc "Handle oauth with multiple authenticating authorities."
|
||||
:author "Simon Brooke"} youyesyet.oauth
|
||||
(:require [youyesyet.config :refer [env]]
|
||||
[youyesyet.db.core :as db]
|
||||
[oauth.client :as oauth]
|
||||
[mount.core :refer [defstate]]
|
||||
[clojure.tools.logging :as log]))
|
||||
|
||||
(defstate consumer
|
||||
:start (oauth/make-consumer
|
||||
(env :oauth-consumer-key)
|
||||
(env :oauth-consumer-secret)
|
||||
(env :request-token-uri)
|
||||
(env :access-token-uri)
|
||||
(env :authorize-uri)
|
||||
:hmac-sha1))
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;
|
||||
;;;; youyesyet.routes.home: routes and pages for unauthenticated users.
|
||||
;;;;
|
||||
;;;; This program is free software; you can redistribute it and/or
|
||||
;;;; modify it under the terms of the GNU General Public License
|
||||
;;;; as published by the Free Software Foundation; either version 2
|
||||
;;;; of the License, or (at your option) any later version.
|
||||
;;;;
|
||||
;;;; This program is distributed in the hope that it will be useful,
|
||||
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;;; GNU General Public License for more details.
|
||||
;;;;
|
||||
;;;; You should have received a copy of the GNU General Public License
|
||||
;;;; along with this program; if not, write to the Free Software
|
||||
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
;;;; USA.
|
||||
;;;;
|
||||
;;;; Copyright (C) 2016 Simon Brooke for Radical Independence Campaign
|
||||
;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
(defn get-authorities
|
||||
"Fetch the authorities from the database and return a map of them."
|
||||
[_]
|
||||
(reduce
|
||||
merge
|
||||
{}
|
||||
(map
|
||||
(fn [authority]
|
||||
(hash-map
|
||||
(:id authority)
|
||||
(oauth/make-consumer
|
||||
(:consumer_key authority)
|
||||
(:consumer_secret authority)
|
||||
(:request_token_uri authority)
|
||||
(:access_token_uri authority)
|
||||
(:authorize_uri authority)
|
||||
:hmac-sha1)))
|
||||
(db/list-authorities db/*db* {}))))
|
||||
|
||||
|
||||
(def authority!
|
||||
;; Closure to allow authorities to be created once when the function is first
|
||||
;; called. The argument `id` should be a string, the id of some authority
|
||||
;; known to the database. As side-effect, the key `:authority` is bound in the
|
||||
;; session to the selected authority.
|
||||
(let [authorities (atom nil)]
|
||||
(fn [id]
|
||||
(if
|
||||
(nil? @authorities)
|
||||
(do
|
||||
(log/debug "Initialising authorities map")
|
||||
(swap!
|
||||
authorities
|
||||
get-authorities)))
|
||||
(let
|
||||
[authority (@authorities id)]
|
||||
(if authority
|
||||
(do
|
||||
(log/debug (str "Selected authority " id))
|
||||
(session/put! :authority authority)))
|
||||
authority))))
|
||||
|
||||
(defn oauth-callback-uri
|
||||
"Generates the oauth request callback URI"
|
||||
"Generates the oauth request callback URI."
|
||||
[{:keys [headers]}]
|
||||
(str (headers "x-forwarded-proto") "://" (headers "host") "/oauth/twitter-callback"))
|
||||
(str (headers "x-forwarded-proto") "://" (headers "host") "/oauth/oauth-callback"))
|
||||
|
||||
(defn fetch-request-token
|
||||
"Fetches a request token."
|
||||
"Fetches a request token from the authority implied by this `request`."
|
||||
[request]
|
||||
(let [callback-uri (oauth-callback-uri request)]
|
||||
(log/info "Fetching request token using callback-uri" callback-uri)
|
||||
(oauth/request-token consumer (oauth-callback-uri request))))
|
||||
(let [callback-uri (oauth-callback-uri request)
|
||||
auth-id (:authority (:params request))
|
||||
auth (authority! auth-id)]
|
||||
(log/info "Attempting to authorise with authority " auth-id)
|
||||
(if
|
||||
auth
|
||||
(do
|
||||
(log/info "Fetching request token using callback-uri" callback-uri)
|
||||
(oauth/request-token auth (oauth-callback-uri request)))
|
||||
(throw (Exception. (str "No such authority: " auth-id))))))
|
||||
|
||||
(defn fetch-access-token
|
||||
[request_token]
|
||||
(oauth/access-token consumer request_token (:oauth_verifier request_token)))
|
||||
(oauth/access-token (session/get :authority) request_token (:oauth_verifier request_token)))
|
||||
|
||||
(defn auth-redirect-uri
|
||||
"Gets the URI the user should be redirected to when authenticating."
|
||||
[request-token]
|
||||
(str (oauth/user-approval-uri consumer request-token)))
|
||||
(str (oauth/user-approval-uri (session/get :authority) request-token)))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
(ns
|
||||
youyesyet.routes.auto
|
||||
"User interface routes for Youyesyet auto-generated by [Application Description Language framework](https://github.com/simon-brooke/adl) at 20180629T101059.328Z"
|
||||
"User interface routes for Youyesyet auto-generated by [Application Description Language framework](https://github.com/simon-brooke/adl) at 20180629T141538.443Z"
|
||||
(:require
|
||||
[adl-support.core :as support]
|
||||
[clojure.java.io :as io]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
(ns
|
||||
youyesyet.routes.auto-json
|
||||
"JSON routes for youyesyet auto-generated by [Application Description Language framework](https://github.com/simon-brooke/adl) at 20180629T101058.294Z"
|
||||
"JSON routes for youyesyet auto-generated by [Application Description Language framework](https://github.com/simon-brooke/adl) at 20180629T141537.425Z"
|
||||
(:require
|
||||
[adl-support.core :as support]
|
||||
[clojure.java.io :as io]
|
||||
|
|
@ -118,6 +118,7 @@
|
|||
search-strings-team
|
||||
search-strings-visit
|
||||
update-address!
|
||||
update-authority!
|
||||
update-canvasser!
|
||||
update-district!
|
||||
update-dwelling!
|
||||
|
|
@ -553,6 +554,10 @@
|
|||
"/json/auto/update-address"
|
||||
request
|
||||
(route/restricted (update-address! request)))
|
||||
(POST
|
||||
"/json/auto/update-authority"
|
||||
request
|
||||
(route/restricted (update-authority! request)))
|
||||
(POST
|
||||
"/json/auto/update-canvasser"
|
||||
request
|
||||
|
|
@ -1224,6 +1229,13 @@
|
|||
(do (db/update-address! params))
|
||||
(response/found "/"))
|
||||
|
||||
(defn
|
||||
update-authority!
|
||||
"Auto-generated method to update one record in the `authorities` table. Expects the following key(s) to be present in `params`: `(nil)`."
|
||||
[{:keys [params]}]
|
||||
(do (db/update-authority! params))
|
||||
(response/found "/"))
|
||||
|
||||
(defn
|
||||
update-canvasser!
|
||||
"Auto-generated method to update one record in the `canvassers` table. Expects the following key(s) to be present in `params`: `(nil)`."
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
[ring.util.http-response :refer [content-type ok]]
|
||||
[youyesyet.layout :as layout]
|
||||
[youyesyet.db.core :as db-core]
|
||||
[youyesyet.oauth :as oauth]
|
||||
[compojure.core :refer [defroutes GET POST]]
|
||||
[ring.util.http-response :as response]
|
||||
[clojure.java.io :as io]))
|
||||
|
|
@ -77,13 +78,15 @@
|
|||
(defn login-page
|
||||
"This is very temporary. We're going to do authentication by oauth."
|
||||
[request]
|
||||
(let [params (keywordize-keys (:form-params request))
|
||||
(let [params (keywordize-keys (:params request))
|
||||
session (:session request)
|
||||
username (:username params)
|
||||
user (if username (db-core/get-canvasser-by-username db-core/*db* {:username username}))
|
||||
password (:password params)
|
||||
redirect-to (or (:redirect-to params) "roles")]
|
||||
(cond
|
||||
(:authority params)
|
||||
(oauth/fetch-request-token request)
|
||||
;; this is obviously, ABSURDLY, insecure. I don't want to put just-about-good-enough,
|
||||
;; it-will-do-for-now security in place; instead, I want this to be test code only
|
||||
;; until we have o-auth properly working.
|
||||
|
|
@ -92,7 +95,7 @@
|
|||
user
|
||||
(layout/render "login.html" {:title (str "User " username " is unknown") :redirect-to redirect-to})
|
||||
true
|
||||
(layout/render "login.html" {:title "Please log in" :redirect-to redirect-to}))))
|
||||
(layout/render "login.html" {:title "Please log in" :redirect-to redirect-to :authorities (db-core/list-authorities db-core/*db*)}))))
|
||||
|
||||
|
||||
(defroutes home-routes
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
[clojure.tools.logging :as log]))
|
||||
|
||||
(defn oauth-init
|
||||
"Initiates the Twitter OAuth"
|
||||
"Initiates the OAuth with the authority implied by this `request`"
|
||||
[request]
|
||||
(-> (oauth/fetch-request-token request)
|
||||
:oauth_token
|
||||
|
|
@ -15,11 +15,11 @@
|
|||
found))
|
||||
|
||||
(defn oauth-callback
|
||||
"Handles the callback from Twitter."
|
||||
"Handles the callback from the authority."
|
||||
[request_token {:keys [session]}]
|
||||
; oauth request was denied by user
|
||||
(if (:denied request_token)
|
||||
(-> (found "/")
|
||||
(-> (found "/login")
|
||||
(assoc :flash {:denied true}))
|
||||
; fetch the request token and do anything else you wanna do if not denied.
|
||||
(let [{:keys [user_id screen_name]} (oauth/fetch-access-token request_token)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue