git clone ''

(ql:quickload :molst.annagreta)

annagreta is a Clojure authorization library.


Annagreta does NOT

Getting Started

The core concept in annagreta is the notion of an ‘auth-key’ that can look like this: clj {:token "abcd" :locks {:member "" :watch-user ["" ""] :pages ["^*"] :widgets ["stocks" "weather"]}} This key is idenfitied by a token and can unlock a bunch of locks. The keys in ‘locks’ are totally arbitrary and depends on the design of the system using annagreta. A value like this can be loaded from annagreta and passed around to unlock functionality in a program. By being a value, it can also easily be passed around between different systems.

The following sections is about explaining how to resolve a request like this: http://localhost/hello-world-resource?member=""&auth-key="abcd" It could show the client a user specific page if there is a key in the annagreta database that is identified by token “abcd” and has a lock for key :member with a value of “”, and another if no such key is found.

The unlocking of a feature is as simple as this: clj (if (anna/unlocks? auth-key :widget "weather") (current-weather-html) (santa-claus))

There are also helper functions to make dealing with the typical use case of keys unlocking private functionality for a member in a system: clj (if (member/unlocks-member? auth-key {:person/primary-email ""}) (current-weather-html) (santa-claus))

A more complete example of granting a user a page view: ```clj (ns (:require [net.cgrand.moustache :as moustache]) (:require [torpo.uri :as uri]) (:require [treq.core :as treq]) (:require [annagreta.treq :as annatreq]) (:require [annagreta.member :as member]))

(defn annapick “Pick stuff according to the supplied (optional) map from annagreta. Always picks :member :auth-key identified by the corresponding request parameters from annagreta.” [req & [pick-map]] (let [auth-uri (uri/merge annagreta-base-uri (annatreq/auth-req-to-uri req))] (treq/pick http/block-read! auth-uri ;as the request parameters are a natural flat map, or the top of a tree, treq is a good fit for resolving the params (merge (select-keys (:params auth-uri) [:member :auth-key]) pick-map))))

;This handler is taking care of requests like “http://localhost/hello-world-resource?member=”“&auth-key=”abcd“ (defn hello-world-route-handler [req] (let [{:keys [member auth-key]} (annapick req)] ;picks member and auth-key from annagreta (if (member/unlocks-member? auth-key member) {:body ”hello world GRANTED!!!“} {:body ”go home"}))

(def routes (→ (moustache/app [“hello-world-resource”] (moustache/app :get hello-world-route-handler)) ```

It is just as easy to grant functionality at a lower program level:

(ns webstuff
  (:require [annagreta.core :as anna])
  (:require [annagreta.person :as person])
  (:require [annagreta.member :as member]))

(defn some-html-div [{:keys [member auth-key]}]
  (let [member-map (person/make-id-person member)
        member-id (person/get-id member-map)]
      (if (member/unlocks-member? auth-key member-map)
         [:li [:a {:href (str "" (:person/nickname member))} "Your personal link"]]
         [:li [:a {:href ""} "Non-personal link"]]]))
      (when (anna/unlocks? auth-key :widget "weather")
        [:div (weather-widget)])]))

Notice that the function generates HTML data. Even if the HTML is hosted on Clojure in this case, rather than on something XMLish, the semantics are just the same and should be familiar to any web developer.

Project Maturity

NOT very well tested. Might contain severe bugs. Have never been used on a production web site. Developed primarily for my personal use. Anything can change without notice.


on Clojars. If you are using Maven, add the following repository definition to your pom.xml:


With Leiningen: [annagreta "0.1"]

Major dependencies


Copyright (C) 2013 Marcus Holst

Licensed under the Eclipse Public License v1.0 (the same as Clojure).