This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-08-16
Channels
- # announcements (3)
- # beginners (104)
- # boot (18)
- # calva (1)
- # cider (43)
- # cljs-dev (45)
- # cljsrn (2)
- # clojure (29)
- # clojure-dev (10)
- # clojure-europe (2)
- # clojure-italy (117)
- # clojure-nl (17)
- # clojure-spec (56)
- # clojure-uk (41)
- # clojuredesign-podcast (12)
- # clojurescript (35)
- # community-development (6)
- # cursive (27)
- # datomic (12)
- # emacs (9)
- # fulcro (6)
- # graalvm (52)
- # instaparse (6)
- # klipse (3)
- # leiningen (11)
- # lumo (1)
- # off-topic (16)
- # pathom (31)
- # re-frame (10)
- # reagent (26)
- # reitit (3)
- # shadow-cljs (67)
- # sql (4)
- # tools-deps (1)
Today is the first day that I write Clojure professionally; for real money 😍
Hey, so it is now time for me to learn about security - I know this is an absolutely HUGE topic for the scope of this slack, but I wanted to know if anyone here had used buddy
for creating sign in tokens? My goal is to have the user submit their username and password once and only once, receive a token that is valid for a certain amount of time, and use that for all further communication. However, having never touched security before, I'm trying to find my entry point. Is buddy-sign
a good package for this? Tough position to be in
im probably going to follow this, just intimidated https://rundis.github.io/blog/2015/buddy_auth_part1.html
@ashley this seems to be a more recent tutorial: https://funcool.github.io/buddy-auth/latest/
The Signed JWT Auth Example
is probably what you'd want?
It sounds like it but im not quite sure how it truly works
@ashley this is not an answer to your question, but I think it's a great high-level talk about key topics in web security for Clojure apps per OWASP https://www.youtube.com/watch?v=lRHPZXKQVLk
I'll give it a watch as that sounds like something I need to see
it will give you a map for thinking about it at least
I'm not sure about the 'self contained' part of the JWT auth example, if the client doesn't accept the token, how does the server distinguish between clients?
This type of token mechanism enables a complete stateless authentication because the server does not need to store the token and related information, the token will contain all the needed information for authentication.
So, I don't understand this because it refers to this needed information
, but I don't know what exactly this isso the idea here is to just allow allowed clients to talk to the server. the token is digitally signed by the server before handing it out. all subsequent requests must have this
my understanding is that a token is like a temporary password. You sign in and you get given a token for your use of the site. When you request data you use your token - but if everything is self contained on the server, what does the client get from signing in, and how is the server stateless
if it is actually managing the currently active tokens
So the token is still given out?
https://jwt.io/ is a good start for understanding jwt
if the client has valid creds
the user ID is contained directly in the token information, and as long as the token is signed by the server, the server can trust its own signatures
yeah, I'll go watch some videos that people have recommended as it seems these kinds of guides expect a basic understanding of the terminology otherwise I'll fail to understand the details like we just discussed. When it said everything is self contained.
I was thinking it was referring to the server, not the token. Okay I get it
But you can ignore all of the specifics about JSON web tokens and think: encrypt(key, data_payload) == token
controversial as in.. I shouldn't be learning to use them, or just that there has been and that its okay to use?
Depends on which security professional you talk to, but in the early days of JWTs, many of the libraries had terrible defaults.
That buddy page says this:
In order to use any asymmetric encryption algorithm, you should have private/public key pair. If you don’t have one, don’t worry, it is very easy to generate it using openssl, see this faq entry.
You think I should ignore that advice and do something else?Hmm, no. In terms of types, I have a database server, my API server and my frontend server. In the future people might want multiple quantities of each but I'd have to learn docker swarms first. I'm taking it slow and doing one of each - but I don't know if I need new servers for this stuff
Haha 🙂 I guess you could say I'm a little chatty because it's how I mainly learn - as you can probably gather from the amount of questions I ask here
I also never take my fingers off the keyboard so I'm kind of just used to keybindings and doing things fairly quick
Im eating lunch now though so taking it easy, then I'll watch those videos and have a shower while I think about my plan of attack
Thank you very very much 🙂 I really cannot wait to get over this hurdle as its kind of the last big 'thing' I haven't touched, after this it should be game over 🙂
If you use JWTs over session cookies for authentication, there are a couple things to look out for:
- Server-side rendering just became impossible because JWTs stored in local/session storage have to be sent with an XHR request
- If you provide downloads that require the user to be authenticated, you will have to either guarantee that downloads are small enough to use something like URL.createObjectURL
in the browser, or you will have to generate short-lived, one-off URLs that do not require authentication
- Local/session storage are not actually secure. If a JWT is stored in session storage, then entering sessionStorage
in the Chrome dev tools will output all session storage tokens, making it possible to hijack a JWT from one user, call sessionStorage.setItem('{key}', '{other_users_jwt}')
in dev tools for another session, and effectively be logged in as the first user. There are probably ways around this, but IMO it’s better to use session cookies.
What is the state of a Clojure targeting .NET
@UEQGQ6XH7 I suggest you listen to http://vijaykiran.com/2019/04/defn-48-david-miller/
ClojureCLR?
It exists. David Miller does a lot of work on it to bring it up to date with features added to Clojure/Java version. According to Clojure surveys, it is used by a fairly small fraction of Clojure developers (about 2% of those who responded to 2019 survey). I personally have not used .NET for developing anything, Clojure or otherwise, so am not the right person to give more details.
Would it be safe to develop anything with it?
depends how you measure safety :)
afaik it works and is a reasonable close port of the jvm version
the number of users is quite small though. the arcadia unity project is easily the biggest thing I know of based on it
(I do not know of anything else)
Do you think support will drop at some point?
Haha :)
@seancorfield: I'm using depstar
along with a process to do AOT in preparation to create a native-image
with the GraalVM.
{:deps {org.clojure/clojure {:mvn/version "1.10.1"}}
:aliases {:aot {:extra-paths ["classes"]
:main-opts ["-e" "(compile,'clj-graalvm.core)"]}
:depstar {:extra-deps {seancorfield/depstar {:mvn/version "0.3.1"}}}}}
and I can generate the jar with:
clojure -A:depstar:aot -m hf.depstar.uberjar clj-graalvm.jar -m clj_graalvm.core -v
and run it:
java -jar clj-graalvm.jar
👋 1.10.1
but, I can't produce a native-image
:
native-image --report-unsupported-elements-at-runtime --initialize-at-build-time -jar clj-graalvm.jar
Build on Server(pid: 41171, port: 57235)
[clj-graalvm:41171] classlist: 1,114.78 ms
[clj-graalvm:41171] (cap): 942.79 ms
[clj-graalvm:41171] setup: 1,165.54 ms
[clj-graalvm:41171] analysis: 4,439.00 ms
Warning: Aborting stand-alone image build. Class initialization of clj_graalvm.core failed. Use the option --initialize-at-run-time=clj_graalvm.core to explicitly request delayed initialization of this class.
Detailed message:
Warning: Use -H:+ReportExceptionStackTraces to print stacktrace of underlying exception
Build on Server(pid: 41171, port: 57235)
[clj-graalvm:41171] classlist: 139.48 ms
[clj-graalvm:41171] (cap): 927.01 ms
[clj-graalvm:41171] setup: 1,141.24 ms
[clj-graalvm:41171] (typeflow): 1,248.20 ms
[clj-graalvm:41171] (objects): 1,359.97 ms
[clj-graalvm:41171] (features): 104.56 ms
[clj-graalvm:41171] analysis: 2,760.68 ms
[clj-graalvm:41171] (clinit): 67.37 ms
[clj-graalvm:41171] universe: 142.82 ms
[clj-graalvm:41171] (parse): 218.14 ms
[clj-graalvm:41171] (inline): 542.06 ms
[clj-graalvm:41171] (compile): 1,023.42 ms
[clj-graalvm:41171] compile: 1,923.44 ms
[clj-graalvm:41171] image: 213.90 ms
[clj-graalvm:41171] write: 130.16 ms
[clj-graalvm:41171] [total]: 6,488.63 ms
Warning: Image 'clj-graalvm' is a fallback image that requires a JDK for execution (use --no-fallback to suppress fallback image generation).
native-image and clojure 1.10.1 are not compatible @johnjelinek
which version should I be using?
Will do
I just wanna make a few simple single-binary non-JVM CLI apps
I’m having difficulties making a multipart POST request with http-kit to the google drive rest api. Everything works with Postman, but I can’t figure out the configuration with http-kit/post or http-kit/request. Has anyone done this?
I’m working on a PR for a library, and I’d like to test it locally in a different deps.edn
project. However, I can’t quite figure out what the best way to require the local copy. Are people using deps :aliases
for that?
I’ve tried the :alias
approach, but the library is a lein
project and I’m getting Manifest type not detected when finding deps
What's the difference b/w vars and atoms?
How is alter-var-root
diff. from swap!
, except from the retry in the atom case?
What happens when multiple threads try to alter a var root and fail?
alter-var-root doesn't fail AFAIK, it's just serialized?
swap! is faster if lack of contention is the common case
alter-var-root just locks while updating so the contender has to wait
it's slower thanks to the lock (which an atom doesn't need)
@jaihindhreddy have you read this page? https://clojure.org/reference/vars it tries to explain how var differs from the other mutable types (I thought it explained all four but they're spread across multiple pages)
Read this page and the atom page before posting here but still didn't get it. Now I understand that alter-var-root locks the var whereas atom leverages CAS with retries.
There's also the per-thread dynamic aspect of vars
alter-var-root calls out to this, which thanks to synchronized
uses locking implicitly https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Var.java#L307
swap! calls this, no locking or synchronization (uses compareAndSet and retries until success instead) https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Atom.java#L33
@seancorfield: I'm using https://github.com/clojure/tools.cli and encountering interesting behavior:
(defn default-repository-name []
(->> (clojure.string/split (-> (java.io.File. ".") .getAbsolutePath) #"/")
reverse
second))
I was expecting that if I ran my application from different locations, then the default would render differently:
$ pwd
/vault-policy-generator/wat
$ ../vault-policy-generator -h
This reviews your repository and spits out appropriate vault policies.
Usage: vault-policy-generator [options]
Options:
-d, --database NAME Database Name
-n, --name NAME vault-policy-generator Repository name
-h, --help
I was expecting it to say -n, --name NAME wat Repository name
☝️
(def cli-options
[["-d" "--database NAME" "Database Name (web or pos)"]
["-n" "--name NAME" "Repository name"
:default (default-repository-name)]
["-h" "--help"]])
@johnjelinek you built an uberjar?
(With AOT I'm guessing)
def computes the value at compile time
So AOT compiles it and that's the value it gets for all time.
What's the right way to tell to to come up with this value at runtime?
Build the uberjar WITHOUT AOT and it will do what you want
But then you'll need to run it differently
(I'm on vacation in England so I'm typing on my phone -- explanation is limited 😁)
Is there a way to keep AOT and still allow this to be evaluated at runtime?
OH! 😆 we don't have to figure this out right now, go vacation!
Make it a defn with no args and call it
(cli-options)
At work we just don't use AOT at all
OH! 😆 good catch!
😆 that's why I'm in #beginners