SlideShare a Scribd company logo
Frameworkless Web Development in Clojure
Andreas ’Kungi’ Klein
24.01.2015
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 1 / 21
Outline
1 Web programming in Clojure
2 HTTP Abstraction
3 Routing
4 HTML Templating
5 Authentication
6 Conclusion
7 Bibliography
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 2 / 21
Web programming in Clojure
What’s I like?
No dominant web frameworks
No framework dependent paradigms
Just plain clojure data structures and functions
The full power of clojure is available in every ”step”
Web programming from the bottom up
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 3 / 21
What’s nice to have for web programming?
The typical web framework offers:
Web Server / HTTP abstraction
Middlewares
Session
CSRF Protection
Request Routing
HTML Templating
Authentication
(Database abstraction)
(Communication with the frontend)
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 4 / 21
Clojure’s libraries
Feature Library
HTTP Abstraction Ring
Middlewares Ring
Routing Clout / Compojure
HTML Templating Hiccup / Enlive
Authentication Friend
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 5 / 21
What is Ring?
Ring is the most widely used Clojure interface between web servers and web
applications.
Similar technologies in other languages include
Plack (Perl)
Rack (Ruby)
Clack (Common Lisp)
WSGI (Python)
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 6 / 21
Ring concepts
Client
Adapter
HTTP
Request
Ring
Request
Middleware
Ring
Request
Handler
Adapter
HTTP
Response
Ring
Response
Middleware
Ring
Response
Requests, Responses, Middlewares, Handlers, Adapters
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 7 / 21
Ring example
Example project.clj
:dependencies [[org.clojure/clojure "1.6.0"]
[ring/ring-core "1.3.2"]]
:plugins [[lein-ring "0.9.1"]]
:ring {:handler ring-example.core/handler}
Example Ring handler
(ns ring-example.core)
(defn handler [request]
{:status 200
:headers {"Content-Type" "text/html"}
:body "Hello World"})
Start with
lein ring server
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 8 / 21
Request / Response
Requests and responses are maps (see ring spec)
(require '[ring.mock.request :as mock])
(mock/request :get "/hallo")
=> {:server-port 80
:server-name "localhost"
:remote-addr "localhost"
:uri "/hallo"
:query-string nil
:scheme :http
:request-method :get
:headers {"host" "localhost"}}
(handler (mock/request :get "/hallo"))
=> {:headers {"Content-Type" "text/html"}
:status 200
:body "Hello World"}
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 9 / 21
Middleware
A middleware is a higher order function that enhances a handler. The first
argument is a handler-function and the middleware itself returns a handler
function.
(defn wrap-content-type [handler content-type]
(fn [request]
(let [response (handler request)]
(assoc-in response [:headers "Content-Type"] content-type))))
Usage
(def app
(-> handler
(wrap-content-type "text/html")))
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 10 / 21
Adapter
Adapters translate from a concrete web server to ring requests and responses. For
example ring.adapter.jetty as the name suggests connects ring to jetty. This
is where most of the magic happens:
(defn- proxy-handler
"Returns an Jetty Handler implementation
for the given Ring handler."
[handler]
(proxy [AbstractHandler] []
(handle [_ ^Request base-request request response]
(let [request-map (servlet/build-request-map request)
response-map (handler request-map)]
(when response-map
(servlet/update-servlet-response response
response-map)
(.setHandled base-request true))))))
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 11 / 21
Clout
Clout is an HTTP matching library using the same syntax as Rails or Sinatra.
(require '[clout.core :as clout])
(require '[ring.mock.request :as mock])
(clout/route-matches "/article/:title/author/:name"
(mock/request :get "/article/clojure/author/rich"))
=> {:title "clojure" :name "rich"}
(clout/route-matches "/article/:title"
(mock/request :get "schnuff-schnuff"))
=> nil
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 12 / 21
Compojure
Most of the time Clout is used through compojure. Compojure combines ring and
clout through a concise syntax.
(require '[compojure.core :refer [GET POST defroutes]])
(require '[ring.util.response :refer [redirect-after-post]])
(defroutes app
(GET "/article/:title" [title]
(str "Found article " title))
(POST "/article" request
(let [article (create-article (:body request))]
(reqirect-after-post (str "/article/" (:id article))))))
Compojure routes are ring handlers.
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 13 / 21
Hiccup
Hiccup is a literal translation from HTML to clojure vectors and maps.
(use 'hiccup.page)
(html5
[:head [:title "How much do I love clojure?"]]
[:body [:h1 "Very Much!"]])
=> "<!DOCTYPE html>
<html>
<head><title>How much do I love clojure?</title></head>
<body><h1>Very Much!</h1></body>
</html>"
It also provides some CSS selector like shortcuts.
[:div#id.class-1.class2 "Schnuff!"]
=> "<div class="class-1 class2" id="id">Schnuff!</div>"
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 14 / 21
Enlive
A completely different strategy to HTML templating is provided by Enlive. It
works with selectors and transformations.
Suppose the following HTML exists in test.html:
<!DOCTYPE html>
<html lang="en">
<head><title>This is a title placeholder</title></head>
<body><ul></ul></body>
</html>
(use '[net.cgrand.enlive-html])
(deftemplate main-template "test.html"
[foo]
[:head :title] (content (str "Enlive starter kit: " foo))
[:body :ul] (do-> (add-class "item-list")
(append (html [:li "Item 1"]))
(append (html [:li "Item 2"]))))
deftemplate creates a function which returns html.
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 15 / 21
Friend
Friend calls itself an ”extensible authentication and authorization library for
Clojure Ring web applications and services.”
Works very well with ring/compojure
Provides role based authentication
Friend contains two mayor concepts
Credential functions
Authentication workflows (e.g. OAuth, HTTP Basic Auth, Login Form, …)
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 16 / 21
Credential function example
A credential function returns either nil or a map representing the credentials like
{:username "joe"
:app.foo/passphrase "bcrypt hash"}
(defn bcrypt-credential-fn
[load-credentials-fn {:keys [username password]}]
(when-let [creds (load-credentials-fn username)]
(let [password-key (or (-> creds meta ::password-key)
:password)]
(when (bcrypt-verify password (get creds password-key))
(dissoc creds password-key)))))
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 17 / 21
Workflow example
A workflow function either returns an authorization map containing the users
credentials or it delivers an error page depending on the kind of workflow. The
interactive-form workflow for example delivers a login page in case of failure.
See the following simplified example from the friend source:
(defn http-basic
[& {:keys [credential-fn realm] :as basic-config}]
(fn [{{:strs [authorization]} :headers :as request}]
(when (and authorization (re-matches #"s*Basics+(.+)" authorization))
(if-let [[[_ username password]] (extract-username-password ...)]
(if-let [user-record
((gets :credential-fn
basic-config
(::friend/auth-config request))
^{::friend/workflow :http-basic}
{:username username, :password password})]
(make-auth user-record
{::friend/workflow :http-basic
::friend/redirect-on-auth? false
::friend/ensure-session false})
(http-basic-deny realm request))
{:status 400
:body "Malformed Authorization header for HTTP Basic authentication."}))))
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 18 / 21
Putting it together
(ns your.ring.app
(:require [cemerick.friend :as friend]
(cemerick.friend [workflows :as workflows]
[credentials :as creds])))
;; a dummy in-memory user "database"
(def users {"root" {:username "root"
:password (creds/hash-bcrypt "admin_password")
:roles #{::admin}}
"jane" {:username "jane"
:password (creds/hash-bcrypt "user_password")
:roles #{::user}}})
(def ring-app
;; ... assemble routes however you like ...
)
(def secured-app
(-> ring-app
(friend/authenticate
{:credential-fn (partial creds/bcrypt-credential-fn users)
:workflows [(workflows/interactive-form)]})
;; ...required Ring middlewares ...
))
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 19 / 21
Frameworkless Web Development
What’s great about Frameworkless?
Small libraries can be composed easily
Communication between these libraries is easy because plain old clojure data
structures are used
Systems become easier through separation of concerns
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 20 / 21
Bibliography
https://github.com/ring-clojure/ring
https://github.com/weavejester/clout
https://github.com/weavejester/compojure
https://github.com/weavejester/hiccup
https://github.com/cgrand/enlive
https://github.com/cemerick/friend
Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 21 / 21

More Related Content

KEY
Html5 For Jjugccc2009fall
KEY
#NewMeetup Performance
PDF
Meetup Performance
PDF
How to make Ajax work for you
PDF
Web Components
PPTX
Top 10 HTML5 features every developer should know!
PDF
Introduction to web components
PDF
Client-side Auth with Ember.js
Html5 For Jjugccc2009fall
#NewMeetup Performance
Meetup Performance
How to make Ajax work for you
Web Components
Top 10 HTML5 features every developer should know!
Introduction to web components
Client-side Auth with Ember.js

What's hot (20)

PDF
Better Selenium Tests with Geb - Selenium Conf 2014
PPT
J query module1
PDF
Chrome enchanted 2015
PPTX
Go Fullstack: JSF for Public Sites (CONFESS 2013)
PPTX
Go Fullstack: JSF for Public Sites (CONFESS 2012)
PDF
HTML5 (and friends) - History, overview and current status - jsDay Verona 11....
PPTX
SharePoint and jQuery Essentials
PDF
Why and How to Use Virtual DOM
PDF
Oleh Zasadnyy "Progressive Web Apps: line between web and native apps become ...
PDF
HTML5: where flash isn't needed anymore
PDF
Simplify AJAX using jQuery
PDF
Top 45 jQuery Interview Questions and Answers | Edureka
PDF
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
PDF
Pragmatic Browser Automation with Geb - GIDS 2015
PDF
Medium TechTalk — iOS
PDF
Bootstrap과 UI-Bootstrap
PPT
J query b_dotnet_ug_meet_12_may_2012
PDF
jQuery Proven Performance Tips & Tricks
PPTX
Python Code Camp for Professionals 3/4
PPTX
Top 10 HTML5 features
Better Selenium Tests with Geb - Selenium Conf 2014
J query module1
Chrome enchanted 2015
Go Fullstack: JSF for Public Sites (CONFESS 2013)
Go Fullstack: JSF for Public Sites (CONFESS 2012)
HTML5 (and friends) - History, overview and current status - jsDay Verona 11....
SharePoint and jQuery Essentials
Why and How to Use Virtual DOM
Oleh Zasadnyy "Progressive Web Apps: line between web and native apps become ...
HTML5: where flash isn't needed anymore
Simplify AJAX using jQuery
Top 45 jQuery Interview Questions and Answers | Edureka
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Pragmatic Browser Automation with Geb - GIDS 2015
Medium TechTalk — iOS
Bootstrap과 UI-Bootstrap
J query b_dotnet_ug_meet_12_may_2012
jQuery Proven Performance Tips & Tricks
Python Code Camp for Professionals 3/4
Top 10 HTML5 features
Ad

Viewers also liked (10)

PDF
Swaggered web apis in Clojure
PDF
ClojuTRE2015: Kekkonen - making your Clojure web APIs more awesome
PDF
Wieldy remote apis with Kekkonen - ClojureD 2016
PDF
Functional web with clojure
PDF
Deconstructing the Functional Web with Clojure
PDF
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
PDF
Ring: Web Apps in Idiomatic Clojure
PDF
Clojure and the Web
PDF
マイクロフレームワークEnkan(とKotowari)ではじめるREPL駆動開発
PPTX
Web programming in clojure
Swaggered web apis in Clojure
ClojuTRE2015: Kekkonen - making your Clojure web APIs more awesome
Wieldy remote apis with Kekkonen - ClojureD 2016
Functional web with clojure
Deconstructing the Functional Web with Clojure
Euroclojure2014: Schema & Swagger - making your Clojure web APIs more awesome
Ring: Web Apps in Idiomatic Clojure
Clojure and the Web
マイクロフレームワークEnkan(とKotowari)ではじめるREPL駆動開発
Web programming in clojure
Ad

Similar to Frameworkless Web Development in Clojure (20)

PPTX
Going Serverless with Azure Functions
PPTX
e-suap - client technologies- english version
PDF
Web Components With Rails
ODP
Knolx session
PDF
[convergese] Adaptive Images in Responsive Web Design
PDF
Ajax Performance Tuning and Best Practices
PDF
Performance Optimization and JavaScript Best Practices
PDF
Build powerfull and smart web applications with Symfony2
ODP
Codegnitorppt
PPTX
JavaScript front end performance optimizations
PDF
Securing Microservices using Play and Akka HTTP
PPTX
Developing your first application using FIWARE
PPT
Web-Technologies 26.06.2003
PDF
VMWorld 2017 Hackathon training: Getting Started with Clarity
PPTX
JavaScript DOM - Dynamic interactive Code
PPTX
PDF
How to create an Angular builder
PPTX
Lec4-WebClientSideExploitation.pptxdslkjhgfkjdshgfkjfhdkjg
PDF
An Introduction to Tornado
PDF
It is not HTML5. but ... / HTML5ではないサイトからHTML5を考える
Going Serverless with Azure Functions
e-suap - client technologies- english version
Web Components With Rails
Knolx session
[convergese] Adaptive Images in Responsive Web Design
Ajax Performance Tuning and Best Practices
Performance Optimization and JavaScript Best Practices
Build powerfull and smart web applications with Symfony2
Codegnitorppt
JavaScript front end performance optimizations
Securing Microservices using Play and Akka HTTP
Developing your first application using FIWARE
Web-Technologies 26.06.2003
VMWorld 2017 Hackathon training: Getting Started with Clarity
JavaScript DOM - Dynamic interactive Code
How to create an Angular builder
Lec4-WebClientSideExploitation.pptxdslkjhgfkjdshgfkjfhdkjg
An Introduction to Tornado
It is not HTML5. but ... / HTML5ではないサイトからHTML5を考える

Recently uploaded (20)

PDF
Exploratory_Data_Analysis_Fundamentals.pdf
PDF
COURSE DESCRIPTOR OF SURVEYING R24 SYLLABUS
PPT
introduction to datamining and warehousing
PDF
737-MAX_SRG.pdf student reference guides
PDF
Level 2 – IBM Data and AI Fundamentals (1)_v1.1.PDF
PDF
PREDICTION OF DIABETES FROM ELECTRONIC HEALTH RECORDS
PDF
PPT on Performance Review to get promotions
PPTX
introduction to high performance computing
PDF
III.4.1.2_The_Space_Environment.p pdffdf
PDF
BIO-INSPIRED HORMONAL MODULATION AND ADAPTIVE ORCHESTRATION IN S-AI-GPT
PDF
Automation-in-Manufacturing-Chapter-Introduction.pdf
PDF
null (2) bgfbg bfgb bfgb fbfg bfbgf b.pdf
PPTX
Current and future trends in Computer Vision.pptx
PDF
keyrequirementskkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
PPTX
Fundamentals of safety and accident prevention -final (1).pptx
PPTX
communication and presentation skills 01
PPTX
MET 305 2019 SCHEME MODULE 2 COMPLETE.pptx
PDF
Unit I ESSENTIAL OF DIGITAL MARKETING.pdf
PPTX
Safety Seminar civil to be ensured for safe working.
PDF
86236642-Electric-Loco-Shed.pdf jfkduklg
Exploratory_Data_Analysis_Fundamentals.pdf
COURSE DESCRIPTOR OF SURVEYING R24 SYLLABUS
introduction to datamining and warehousing
737-MAX_SRG.pdf student reference guides
Level 2 – IBM Data and AI Fundamentals (1)_v1.1.PDF
PREDICTION OF DIABETES FROM ELECTRONIC HEALTH RECORDS
PPT on Performance Review to get promotions
introduction to high performance computing
III.4.1.2_The_Space_Environment.p pdffdf
BIO-INSPIRED HORMONAL MODULATION AND ADAPTIVE ORCHESTRATION IN S-AI-GPT
Automation-in-Manufacturing-Chapter-Introduction.pdf
null (2) bgfbg bfgb bfgb fbfg bfbgf b.pdf
Current and future trends in Computer Vision.pptx
keyrequirementskkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
Fundamentals of safety and accident prevention -final (1).pptx
communication and presentation skills 01
MET 305 2019 SCHEME MODULE 2 COMPLETE.pptx
Unit I ESSENTIAL OF DIGITAL MARKETING.pdf
Safety Seminar civil to be ensured for safe working.
86236642-Electric-Loco-Shed.pdf jfkduklg

Frameworkless Web Development in Clojure

  • 1. Frameworkless Web Development in Clojure Andreas ’Kungi’ Klein 24.01.2015 Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 1 / 21
  • 2. Outline 1 Web programming in Clojure 2 HTTP Abstraction 3 Routing 4 HTML Templating 5 Authentication 6 Conclusion 7 Bibliography Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 2 / 21
  • 3. Web programming in Clojure What’s I like? No dominant web frameworks No framework dependent paradigms Just plain clojure data structures and functions The full power of clojure is available in every ”step” Web programming from the bottom up Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 3 / 21
  • 4. What’s nice to have for web programming? The typical web framework offers: Web Server / HTTP abstraction Middlewares Session CSRF Protection Request Routing HTML Templating Authentication (Database abstraction) (Communication with the frontend) Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 4 / 21
  • 5. Clojure’s libraries Feature Library HTTP Abstraction Ring Middlewares Ring Routing Clout / Compojure HTML Templating Hiccup / Enlive Authentication Friend Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 5 / 21
  • 6. What is Ring? Ring is the most widely used Clojure interface between web servers and web applications. Similar technologies in other languages include Plack (Perl) Rack (Ruby) Clack (Common Lisp) WSGI (Python) Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 6 / 21
  • 7. Ring concepts Client Adapter HTTP Request Ring Request Middleware Ring Request Handler Adapter HTTP Response Ring Response Middleware Ring Response Requests, Responses, Middlewares, Handlers, Adapters Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 7 / 21
  • 8. Ring example Example project.clj :dependencies [[org.clojure/clojure "1.6.0"] [ring/ring-core "1.3.2"]] :plugins [[lein-ring "0.9.1"]] :ring {:handler ring-example.core/handler} Example Ring handler (ns ring-example.core) (defn handler [request] {:status 200 :headers {"Content-Type" "text/html"} :body "Hello World"}) Start with lein ring server Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 8 / 21
  • 9. Request / Response Requests and responses are maps (see ring spec) (require '[ring.mock.request :as mock]) (mock/request :get "/hallo") => {:server-port 80 :server-name "localhost" :remote-addr "localhost" :uri "/hallo" :query-string nil :scheme :http :request-method :get :headers {"host" "localhost"}} (handler (mock/request :get "/hallo")) => {:headers {"Content-Type" "text/html"} :status 200 :body "Hello World"} Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 9 / 21
  • 10. Middleware A middleware is a higher order function that enhances a handler. The first argument is a handler-function and the middleware itself returns a handler function. (defn wrap-content-type [handler content-type] (fn [request] (let [response (handler request)] (assoc-in response [:headers "Content-Type"] content-type)))) Usage (def app (-> handler (wrap-content-type "text/html"))) Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 10 / 21
  • 11. Adapter Adapters translate from a concrete web server to ring requests and responses. For example ring.adapter.jetty as the name suggests connects ring to jetty. This is where most of the magic happens: (defn- proxy-handler "Returns an Jetty Handler implementation for the given Ring handler." [handler] (proxy [AbstractHandler] [] (handle [_ ^Request base-request request response] (let [request-map (servlet/build-request-map request) response-map (handler request-map)] (when response-map (servlet/update-servlet-response response response-map) (.setHandled base-request true)))))) Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 11 / 21
  • 12. Clout Clout is an HTTP matching library using the same syntax as Rails or Sinatra. (require '[clout.core :as clout]) (require '[ring.mock.request :as mock]) (clout/route-matches "/article/:title/author/:name" (mock/request :get "/article/clojure/author/rich")) => {:title "clojure" :name "rich"} (clout/route-matches "/article/:title" (mock/request :get "schnuff-schnuff")) => nil Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 12 / 21
  • 13. Compojure Most of the time Clout is used through compojure. Compojure combines ring and clout through a concise syntax. (require '[compojure.core :refer [GET POST defroutes]]) (require '[ring.util.response :refer [redirect-after-post]]) (defroutes app (GET "/article/:title" [title] (str "Found article " title)) (POST "/article" request (let [article (create-article (:body request))] (reqirect-after-post (str "/article/" (:id article)))))) Compojure routes are ring handlers. Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 13 / 21
  • 14. Hiccup Hiccup is a literal translation from HTML to clojure vectors and maps. (use 'hiccup.page) (html5 [:head [:title "How much do I love clojure?"]] [:body [:h1 "Very Much!"]]) => "<!DOCTYPE html> <html> <head><title>How much do I love clojure?</title></head> <body><h1>Very Much!</h1></body> </html>" It also provides some CSS selector like shortcuts. [:div#id.class-1.class2 "Schnuff!"] => "<div class="class-1 class2" id="id">Schnuff!</div>" Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 14 / 21
  • 15. Enlive A completely different strategy to HTML templating is provided by Enlive. It works with selectors and transformations. Suppose the following HTML exists in test.html: <!DOCTYPE html> <html lang="en"> <head><title>This is a title placeholder</title></head> <body><ul></ul></body> </html> (use '[net.cgrand.enlive-html]) (deftemplate main-template "test.html" [foo] [:head :title] (content (str "Enlive starter kit: " foo)) [:body :ul] (do-> (add-class "item-list") (append (html [:li "Item 1"])) (append (html [:li "Item 2"])))) deftemplate creates a function which returns html. Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 15 / 21
  • 16. Friend Friend calls itself an ”extensible authentication and authorization library for Clojure Ring web applications and services.” Works very well with ring/compojure Provides role based authentication Friend contains two mayor concepts Credential functions Authentication workflows (e.g. OAuth, HTTP Basic Auth, Login Form, …) Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 16 / 21
  • 17. Credential function example A credential function returns either nil or a map representing the credentials like {:username "joe" :app.foo/passphrase "bcrypt hash"} (defn bcrypt-credential-fn [load-credentials-fn {:keys [username password]}] (when-let [creds (load-credentials-fn username)] (let [password-key (or (-> creds meta ::password-key) :password)] (when (bcrypt-verify password (get creds password-key)) (dissoc creds password-key))))) Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 17 / 21
  • 18. Workflow example A workflow function either returns an authorization map containing the users credentials or it delivers an error page depending on the kind of workflow. The interactive-form workflow for example delivers a login page in case of failure. See the following simplified example from the friend source: (defn http-basic [& {:keys [credential-fn realm] :as basic-config}] (fn [{{:strs [authorization]} :headers :as request}] (when (and authorization (re-matches #"s*Basics+(.+)" authorization)) (if-let [[[_ username password]] (extract-username-password ...)] (if-let [user-record ((gets :credential-fn basic-config (::friend/auth-config request)) ^{::friend/workflow :http-basic} {:username username, :password password})] (make-auth user-record {::friend/workflow :http-basic ::friend/redirect-on-auth? false ::friend/ensure-session false}) (http-basic-deny realm request)) {:status 400 :body "Malformed Authorization header for HTTP Basic authentication."})))) Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 18 / 21
  • 19. Putting it together (ns your.ring.app (:require [cemerick.friend :as friend] (cemerick.friend [workflows :as workflows] [credentials :as creds]))) ;; a dummy in-memory user "database" (def users {"root" {:username "root" :password (creds/hash-bcrypt "admin_password") :roles #{::admin}} "jane" {:username "jane" :password (creds/hash-bcrypt "user_password") :roles #{::user}}}) (def ring-app ;; ... assemble routes however you like ... ) (def secured-app (-> ring-app (friend/authenticate {:credential-fn (partial creds/bcrypt-credential-fn users) :workflows [(workflows/interactive-form)]}) ;; ...required Ring middlewares ... )) Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 19 / 21
  • 20. Frameworkless Web Development What’s great about Frameworkless? Small libraries can be composed easily Communication between these libraries is easy because plain old clojure data structures are used Systems become easier through separation of concerns Andreas ’Kungi’ Klein Frameworkless Web Development in Clojure 24.01.2015 20 / 21