This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-08-26
Channels
- # admin-announcements (1)
- # beginners (12)
- # cider (2)
- # cljs-dev (6)
- # cljsrn (4)
- # clojure (123)
- # clojure-austin (10)
- # clojure-brasil (1)
- # clojure-canada (21)
- # clojure-conj (5)
- # clojure-dev (8)
- # clojure-gamedev (42)
- # clojure-russia (121)
- # clojure-sanfrancisco (2)
- # clojure-spec (25)
- # clojure-uk (36)
- # clojurescript (195)
- # clojutre (3)
- # cursive (43)
- # datomic (6)
- # defnpodcast (2)
- # dirac (14)
- # emacs (2)
- # ethereum (2)
- # events (2)
- # funcool (6)
- # hoplon (76)
- # jobs (1)
- # kekkonen (9)
- # lein-figwheel (1)
- # leiningen (4)
- # mount (6)
- # off-topic (5)
- # om (2)
- # onyx (91)
- # pedestal (2)
- # protorepl (14)
- # re-frame (22)
- # reagent (20)
- # rethinkdb (1)
- # ring (2)
- # schema (3)
- # sfcljs (3)
- # spacemacs (15)
- # specter (12)
- # testing (1)
- # yada (63)
I'm a bit confused how :access-control
works. I got it working more or less how I want, but still... I've got in a yada/resource
:
:access-control {:scheme :myns/myscheme
:verify (fn [m] (Logger/info (str "verify-fn: " m)))
:authorization {:methods {:get "role/user"
:put "role/user"}}}
Which means: a user has to have role role/user
to have access to get
and put
methods. This works as expected. From myns/myscheme
, I return nil
or a map with :user
and :roles
keys, or a map with :type
and cause
keys, or I throw an exception.
All well and fine, but
1. I don't see what's the use of :verify
. It seems it is never called. What's the use of verify
in this case?
2. For forbidden access, can I pass a message?
3. What if I want access-control
to comply with 2 schemes? (Is that possible at all? For example: the output of the first one, is piped to the second one etc? - Or so I define a scheme and compose them via functions?)1. The verify function is used by some auth schemes to call back into the resource. It's not applicable to every scheme. Check the implementation of basic auth if you're unsure.
2. Yes, you can. See status responses: https://juxt.pro/yada/manual/index.html#status-responses
3. Authentication schemes are a disjunction (either/or). Multiple authentication schemes allows the user agent to pick one that is suitable. For example, a human might want to authenticate by sending a secret lodged in a brain, a script might want to use an access token. You shouldn't try to implement MFA, 2FA by having 2 auth schemes, rather, you should have one auth scheme that implements the 2FA.
allright... think I get it.
@kurt-yagram let me know if this helps or you need more detail. The HTTP standard is still a little ambiguous in the area of multiple realms and multiple auth-schemes, I've interpreted it as best I can.
The code is pretty confusing actually
Yeah, I'm just trying to get my head around it. It starts to work out bit by bit. I might come back later, but especially point 1 and 3 where important. Got them solved (more or less).
The defmulti is called verify too, which could be the source of confusion. yada calls this defmulti which dispatches to the (yada) verify function for "Basic". (or whatever scheme you're using)
I was implementing JWT stuff - yeah, that's where my confusion came from.
The basic implementation just happens to ALSO have a key called 'verify' which the implementation calls later on.
The 2 verify functions are named the same but are different - gosh that's confusing, sorry!
Right... that's the most confusing part.
I struggled to find a better name at the time
Naming is hard 馃槥
yeah... it is.
But I should rename ,but can't do so now without breaking compatibility - because if I change the yada one then people who have added their own defmethods will complain, and if I change the latter one I break the resource model
Now, just another one: if I return a map like :
{:type :validation
:cause :whatever}
in my defmulti verify
, what exactly happens? I know I will not have access, but what's the use of the :type
and cause
keys?There's still quite a lot more docs on the way for security, so I'll make pains to explain what's going on
let me check, iirc it is merged with the context under :authorization
{:type :validation :cause :whatever}
are the credentials, yada calls (assoc-in ctx [:authentication realm] credentials)
so they appear in the context (be careful of the realm, it defaults to "default")
Credentials established in one 'realm' should not interfere with credentials established in another
ok, so far, so good... Oh ok, and that context I might use in status responses? (Since they are not valid, I'll return status 403
)
- I don't use the realms for now
I can't imagine anyone uses multiple realms, but I've constrained myself to implementing the standard rather than listening to users
If credentials cannot be established (because the user can't be verified, like a bad password was entered, etc.) then you return a 401
If the credentials are established OK, but then you decide later on (in authorization) that the credentials are sufficient for access to the resource, then you return 403
oh yes, right...
it's a painfully subtle distinction 馃槥
and in the 403, I always get:
"error": {
"error": "clojure.lang.ExceptionInfo: Forbidden {:status 403, :headers {}}",
"data": "{:status 403, :headers {}}"
}
Well, it's a logical distinctionHave you tried status responses? Adding {:responses {403 {:response ...}}}
to the resource model?
If it doesn't work, I'll treat that as a bug and fix
Because this is also tied up with the error interceptor chain, I'm pretty sure it will work
nono, not yet, that's the next step. But in the basic implementation, that's the result:
{
"status": 401,
"message": "Unauthorized",
"id": "yada/resource id",
"error": {
"error": "clojure.lang.ExceptionInfo: No authorization provided {:status 401, :headers {}}",
"data": "{:status 401, :headers {}}"
}
}
(similar for 403)well, not basic, but in the default implementation.
@kurt-yagram are you expecting something different? I'm not sure if you're asking me a question here
nono, just a general note. At first, I expected I would be able to add something to it (without using status-responses). I just need to use status-responses for customized messages. All clear for me, thx.
@malcolmsparks is there any support in yada to parse the different parts of a multipart form?
Yes. All supported. See phonebook update which uses a multipart upload.
hmm not sure I'm looking in the right place but I can't find something that looks like this: http://stackoverflow.com/a/9082243
Hey, is patch supported yet? - it seems not but I ask to be sure.
No, not yet. You can add your own implementation though
Allright... saw that. Thanks
this is a sample request I'm sending:
--wdgcgP44AnKGDAdw_3zrrc9tQzvKW5OUVk
Content-Disposition: form-data; name="baz"
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 8bit
5
--wdgcgP44AnKGDAdw_3zrrc9tQzvKW5OUVk
Content-Disposition: form-data; name="qux"
Content-Type: application/json; charset=UTF-8
Content-Transfer-Encoding: 8bit
{"quux":1,"asdf":{"zxcv":"yoyo"}}
--wdgcgP44AnKGDAdw_3zrrc9tQzvKW5OUVk--
and the method trying to catch it is:
{:post
{:parameters {:body {:baz sc/Str
:qux {:quux sc/Int
:asdf {:zxcv sc/Str}}}}
:consumes "multipart/form-data"
:produces "text/plain"
:response (fn [ctx]
(clojure.pprint/pprint (-> ctx :parameters :body))
"")}}
basically I want to abuse multipart in a way that I can send structured data in one of the fields
reason is that I need an endpoint where I can put a multi-level structure plus a file at the same time
Possibly! It's a stretch feature but I could be your friend too :)
I haven't yet managed to get to the bottom of it, but it looks like parameter coercion works different in multipart than outside
fails for a request of
--wdgcgP44AnKGDAdw_3zrrc9tQzvKW5OUVk
Content-Disposition: form-data; name="baz"
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 8bit
5
--wdgcgP44AnKGDAdw_3zrrc9tQzvKW5OUVk--
what seems to be missing is the ability to define the allowed "sub-content-types" that make up the multipart request
:form
(or body) has the following fields:
:count
which coerces from text/plain
to sc/Int
:name
which coerces from text/plain
to sc/Str
(I only managed to get this one working so far)
:file
which is an uploaded file coming as application/octet-stream
for example
:foo-bar
for which we accept application/json
, application/edn
etc. and should coerce to say
{:aa sc/Int
:bb sc/Int
:cc {:dd sc/Int}}