Compare commits

...

6 commits

Author SHA1 Message Date
Simon Brooke 0d21259845 #2: Tighten up security on consumer_secret 2018-08-08 16:27:29 +01:00
Simon Brooke f438803723 #2: I'm getting something back!
That's probably as far as I can get inside the firewall. Now it has to go out!
2018-08-08 16:22:05 +01:00
Simon Brooke 2806d3c28c Merge branch 'develop' into feature/2 2018-08-08 12:48:09 +01:00
Simon Brooke f6d7f238e9 Handle error messages 2018-08-08 12:47:49 +01:00
Simon Brooke a6abeaa679 #2: Started work, not yet working. 2018-08-08 12:45:49 +01:00
Simon Brooke 130d12975d Safety commit
Ran out of electricity last night when I'd almost but not quite got creation working properly. Frustrating! I don't have much electricity this morning so I'm pushing this up to GitHub for safety.
2018-08-06 09:29:56 +01:00
11 changed files with 62 additions and 31 deletions

View file

@ -2,7 +2,6 @@
{% block big-links %} {% block big-links %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<body>
<div class="container-fluid"> <div class="container-fluid">
<div class="row-fluid"> <div class="row-fluid">
<div class="col-lg-12"> <div class="col-lg-12">

View file

@ -2,7 +2,7 @@
{% block big-links %} {% block big-links %}
{% for authority in authorities %} {% for authority in authorities %}
<div class="big-link-container"> <div class="big-link-container">
<a href="auth?authority={{authority.id}}" class="big-link" id="{{authority.id}}-link"> <a href="oauth/oauth-init?authority={{authority.id}}" class="big-link" id="{{authority.id}}-link">
<img src="img/authorities/{{authority.id}}.png" width="32" height="32" alt="{{authority.id}}"/> <img src="img/authorities/{{authority.id}}.png" width="32" height="32" alt="{{authority.id}}"/>
{{authority.id}} {{authority.id}}
</a> </a>

View file

@ -1,5 +1,5 @@
(ns ^{:doc "Handle oauth with multiple authenticating authorities." (ns ^{:doc "Handle oauth with multiple authenticating authorities."
:author "Simon Brooke"} youyesyet.oauth :author "Simon Brooke"} youyesyet.authentication
(:require [youyesyet.config :refer [env]] (:require [youyesyet.config :refer [env]]
[youyesyet.db.core :as db] [youyesyet.db.core :as db]
[oauth.client :as oauth] [oauth.client :as oauth]
@ -8,7 +8,8 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; ;;;;
;;;; youyesyet.routes.home: routes and pages for unauthenticated users. ;;;; youyesyet.authentication: Handle oauth with multiple authenticating
;;;; authorities.
;;;; ;;;;
;;;; This program is free software; you can redistribute it and/or ;;;; This program is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU General Public License ;;;; modify it under the terms of the GNU General Public License
@ -49,6 +50,7 @@
:hmac-sha1))) :hmac-sha1)))
(db/list-authorities db/*db* {})))) (db/list-authorities db/*db* {}))))
(def authority! (def authority!
;; Closure to allow authorities map to be created once when the function is first ;; Closure to allow authorities map to be created once when the function is first
;; called. The argument `id` should be a string, the id of some authority ;; called. The argument `id` should be a string, the id of some authority

View file

@ -91,14 +91,18 @@
(-> #'rest-routes (-> #'rest-routes
(wrap-routes middleware/wrap-formats)) (wrap-routes middleware/wrap-formats))
(-> #'service-routes (-> #'service-routes
(wrap-routes middleware/wrap-formats)) ;; TODO: and authentication, but let's not sweat the small stuff. (wrap-routes middleware/wrap-formats))
'oauth-routes (-> #'oauth-routes
(wrap-routes middleware/wrap-csrf)
(wrap-routes middleware/wrap-formats))
(route/resources "/") (route/resources "/")
(route/not-found (route/not-found
(fn [request]
(log/error "NOT-FOUND: " request)
(:body (:body
(error-page {:status 404 (error-page {:status 404
:title "Page not found" :title "Page not found"
:message "The page you requested has not yet been implemented"}))))) :message (str "The page you requested has not yet been implemented: " (:uri request))}))))))
(def app (middleware/wrap-base #'app-routes)) (def app (middleware/wrap-base #'app-routes))

View file

@ -112,6 +112,7 @@
returns a response map with the error page as the body returns a response map with the error page as the body
and the status specified by the status key" and the status specified by the status key"
[error-details] [error-details]
(log/error "ERROR: " error-details)
{:status (:status error-details) {:status (:status error-details)
:headers {"Content-Type" "text/html; charset=utf-8"} :headers {"Content-Type" "text/html; charset=utf-8"}
:body (render "error.html" {} error-details)}) :body (render "error.html" error-details)})

View file

@ -11,7 +11,7 @@
[youyesyet.config :refer [env]] [youyesyet.config :refer [env]]
[youyesyet.db.core :as db-core] [youyesyet.db.core :as db-core]
[youyesyet.layout :as layout] [youyesyet.layout :as layout]
[youyesyet.oauth :as oauth] [youyesyet.authentication :as auth]
[compojure.core :refer [defroutes GET POST]] [compojure.core :refer [defroutes GET POST]]
)) ))
@ -84,13 +84,13 @@
(str (:servlet-context request) "/roles"))] (str (:servlet-context request) "/roles"))]
(cond (cond
(:authority params) (:authority params)
(let [auth (oauth/authority! (:authority params))] (let [authority (auth/authority! (:authority params))]
(if auth (if authority
(do (do
(log/info "Attempting to authorise with authority " (:authority params)) (log/info "Attempting to authorise with authority " (:authority params))
(oauth/fetch-request-token (auth/fetch-request-token
(assoc request :session (assoc session :authority auth)) (assoc request :session (assoc session :authority authority))
auth)) authority))
(throw (Exception. (str "No such authority: " (:authority params)))))) (throw (Exception. (str "No such authority: " (:authority params))))))
;; this is obviously, ABSURDLY, insecure. I don't want to put just-about-good-enough, ;; 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 ;; it-will-do-for-now security in place; instead, I want this to be test code only

View file

@ -12,13 +12,12 @@
[youyesyet.config :refer [env]] [youyesyet.config :refer [env]]
[youyesyet.db.core :as db] [youyesyet.db.core :as db]
[youyesyet.layout :as layout] [youyesyet.layout :as layout]
[youyesyet.oauth :as oauth]
[compojure.core :refer [defroutes GET POST]] [compojure.core :refer [defroutes GET POST]]
)) ))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; ;;;;
;;;; youyesyet.routes.home: routes and pages for issue experts. ;;;; youyesyet.routes.issue-experts: routes and pages for issue experts.
;;;; ;;;;
;;;; This program is free software; you can redistribute it and/or ;;;; This program is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU General Public License ;;;; modify it under the terms of the GNU General Public License

View file

@ -12,7 +12,6 @@
[youyesyet.config :refer [env]] [youyesyet.config :refer [env]]
[youyesyet.db.core :as db] [youyesyet.db.core :as db]
[youyesyet.layout :as layout] [youyesyet.layout :as layout]
[youyesyet.oauth :as oauth]
[compojure.core :refer [defroutes GET POST]] [compojure.core :refer [defroutes GET POST]]
)) ))

View file

@ -1,22 +1,41 @@
(ns ^{:doc "OAuth authentication routes - not finished, does not work yet." (ns ^{:doc "OAuth authentication routes - not finished, does not work yet."
:author "Simon Brooke"} youyesyet.routes.oauth :author "Simon Brooke"} youyesyet.routes.oauth
(:require [clojure.tools.logging :as log] (:require [adl-support.core :refer :all]
[clojure.tools.logging :as log]
[compojure.core :refer [defroutes GET]] [compojure.core :refer [defroutes GET]]
[ring.util.http-response :refer [ok found]] [ring.util.http-response :refer [ok found]]
[clojure.java.io :as io] [clojure.java.io :as io]
[youyesyet.oauth :as oauth])) [youyesyet.authentication :as auth]
[youyesyet.layout :refer [error-page]]))
(defn oauth-init (defn oauth-init
"Initiates the OAuth with the authority implied by this `request`" "Initiates the OAuth with the authority implied by this `request`"
[request] [request]
;; (-> (oauth/fetch-request-token request) (let [authority-name (:authority (massage-params request))
;; :oauth_token authority (or
;; oauth/auth-redirect-uri (:authority (:session request))
;; found)) (auth/authority! authority-name))]
(found (log/debug "Authenticating with oauth request: " request "; authority: " authority)
(oauth/auth-redirect-uri (if
(:oauth_token (oauth/fetch-request-token request)) authority
(:authority (:session request))))) (do-or-log-error
(assoc-in
(auth/auth-redirect-uri
(:request-token
(auth/fetch-request-token request authority))
authority)
[:session :authority]
authority)
:error-return
{:status 500
:title "Error while seeking authentication"
:message "See server log for more detail"})
(:body
(error-page {:status 404
:title (str "No such authority: " authority-name)
:message "The authority you requested is unknown to this system."})))))
(defn oauth-callback (defn oauth-callback
"Handles the callback from the authority." "Handles the callback from the authority."
@ -27,12 +46,13 @@
(assoc :flash {:denied true})) (assoc :flash {:denied true}))
; fetch the request token and do anything else you wanna do if not denied. ; fetch the request token and do anything else you wanna do if not denied.
(let [{:keys [user_id screen_name]} (let [{:keys [user_id screen_name]}
(oauth/fetch-access-token request_token (:authority session))] (auth/fetch-access-token request_token (:authority session))]
(log/info "successfully authenticated as" user_id screen_name) (log/info "successfully authenticated as" user_id screen_name)
(-> (found "/") (-> (found "/")
(assoc :session (assoc :session
(assoc session :user-id user_id :screen-name screen_name)))))) (assoc session :user-id user_id :screen-name screen_name))))))
(defroutes oauth-routes (defroutes oauth-routes
(GET "/oauth/oauth-init" req (oauth-init req)) (GET "/oauth/oauth-init" req (oauth-init req))
(GET "/oauth/oauth-callback" [& req_token :as req] (oauth-callback req_token req))) (GET "/oauth/oauth-callback" [& req_token :as req] (oauth-callback req_token req)))

View file

@ -11,7 +11,6 @@
[youyesyet.db.core :as db-core] [youyesyet.db.core :as db-core]
[youyesyet.routes.issue-experts :as expert] [youyesyet.routes.issue-experts :as expert]
[youyesyet.layout :as layout] [youyesyet.layout :as layout]
[youyesyet.oauth :as oauth]
[youyesyet.routes.auto :as auto])) [youyesyet.routes.auto :as auto]))
@ -22,7 +21,7 @@
user (-> request :session :user) user (-> request :session :user)
roles (if roles (if
user user
(db-core/list-roles-by-canvasser db-core/*db* {:id (:id user)}))] (db-core/list-roles-by-canvasser db-core/*db* user))]
(log/info (str "Roles routing page; user is " user "; roles are " roles)) (log/info (str "Roles routing page; user is " user "; roles are " roles))
(cond (cond
roles (layout/render "roles.html" roles (layout/render "roles.html"

View file

@ -388,7 +388,14 @@ version="0.1.1">
<property name="consumer-key" type="string" size="32" <property name="consumer-key" type="string" size="32"
required="true" default="youyesyet"/> required="true" default="youyesyet"/>
<property name="consumer-secret" type="string" size="256" <property name="consumer-secret" type="string" size="256"
required="true"/> required="true">
<permission group="canvassers" permission="none"/>
<permission group="teamorganisers" permission="none"/>
<permission group="issueexperts" permission="none"/>
<permission group="analysts" permission="none"/>
<permission group="issueeditors" permission="none"/>
<permission group="admin" permission="all"/>
</property>
<list name="Authorities" properties="listed"> <list name="Authorities" properties="listed">
<field property="id"> <field property="id">
<prompt prompt="id" locale="en_GB.UTF-8"/> <prompt prompt="id" locale="en_GB.UTF-8"/>
@ -782,6 +789,7 @@ version="0.1.1">
</entity> </entity>
<entity table="teams" name="teams" magnitude="4" volatility="4"> <entity table="teams" name="teams" magnitude="4" volatility="4">
<documentation>Organised teams of canvassers who canvass together.</documentation>
<key> <key>
<property type="integer" name="id" column="id" <property type="integer" name="id" column="id"
distinct="system" immutable="true"> distinct="system" immutable="true">