Re: first time without state - and I'm lost

2020-06-16 Thread Oleksandr Shulgin
On Mon, Jun 15, 2020 at 7:34 PM Ernesto Garcia  wrote:

> Hi, it's a long time that this question was posted, but I have found it
> interesting in the implementation of token refreshes.
>
> First of all, for service invocation, given a `revise-oauth-token` method,
> I think this is good client code:
>
> (http/request
>   {:method :get
>:url "https://example.com/";
>:oauth-token (revise-oauth-token token-store)})
>
> If you find it too repetitive or fragile in your client code, you can make
> a local function, but I wouldn't abstract the service invocation at a
> higher layer.
>
> Regarding the implementation of the token store, we could initially think
> of a synchronized store, like an atom, and `revise-oauth-token` would swap
> its content when a refresh is required. This is inconvenient for
> multithreaded clients, because there could be several refresh invocations
> going on concurrently.
>
> In order to avoid concurrent refreshes, I propose to implement the token
> store as an atom of promises. Implementation of `revise-oauth-token` would
> be:
>
> (defn revise-oauth-token [token-store]
>   (:access_token
> @(swap! token-store
>(fn [token-promise]
>  (if (token-needs-refresh? @token-promise (Instant/now))
>(delay (refresh-oauth-token (:refresh_token @token-promise)))
>token-promise)
>
> Note that using a delay avoids running `refresh-oauth-token` within the
> `swap!` operation, as this operation may be run multiple times.
> Also note that `token-needs-refresh` takes an argument with the present
> time. This keeps the function pure, which could help for unit testing, for
> example.
>
> There is an alternative implementation using `compare-and-set!` that
> avoids checking `token-needs-refresh?` several times, but it is more
> complicated. I have posted full sample code in a gist:
> https://gist.github.com/titogarcia/4f09bcc5fa38fbdc1076954b9a99a8fc
>

I think it is worth mentioning an alternative approach to avoid concurrent
token refresh may be to use a scheduled task to run shortly before the
currently valid token is going to expire.
The http call then only needs deref and the background task can even use
reset! on the atom, as there are no concurrent update operations to race
against.

--
Alex

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/clojure/CACACo5TMJPt8CNbk0DS2z%3D%2BVsnadMNRH%3DdPPX%3DBGePWkdRBYXg%40mail.gmail.com.


A template for web apps with user auth using OWASP best practices and pedestal

2020-06-16 Thread Brandon R
Hello,

I've recently been working on building a web app with authentication using
specific libraries and tooling that I wanted to use. I separated that part
out into a separate repo for my own reference later, and for anyone who
might find it useful.

https://github.com/bpringe/auth-template

Features:

   - user sign up with email address
   - email verification via link with token emailed to user
   - user login
   - user logout
   - forgot password / password reset

Tooling:

   - clojure cli
   - pedestal for the backend service
   - java-time for handling time and dates
   - postal for sending emails
   - yogthos/config for configuration
   - next.jdbc for database interaction
   - hiccup for rendering html
   - buddy-hashers for hashing passwords and checking raw passwords against
   stored hashes
   - hikaricp for database connection pooling
   - docker for packaging and deployment
   - shadow-cljs for clojurescript compilation


Happy Clojuring,
Brandon

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/clojure/CAB_6y6GDg5ZW-JtnPWOuX-9_rosmagnj1r10O8of%2BFjM%2B-k2Og%40mail.gmail.com.