Open kseo opened 7 years ago
Hmm I remember I implemented this at some point, but perhaps it never ended up in master.
Related/Duplicates: https://github.com/haskell-servant/servant/issues/463 https://github.com/haskell-servant/servant/issues/672 https://github.com/haskell-servant/servant/issues/465
@arianvp you have an opportunity to close 3 issues with one PR! See also #682
@phadej Due to exams wasn't able to finish this week. however I don't think this should block the 0.10 release. We can do a 0.10.1 release as the changes are non-breaking
@arianvp ack.
Just had the same issue. How can I help?
A HasForeign instance has to be written for the BasicAuth stuff. Which generates enough information such that servant-js
can write auth client code.
Which should be the trivial part: https://stackoverflow.com/questions/5507234/how-to-use-basic-auth-with-jquery-and-ajax
I am a bit busy, so I haven't gotten around doing it yet.
I've just been bitten by this one as well. I'm also willing to help...
Has it just been forgotten for a while? :) It sounded like it was close to being solved.
Yes I haven't had the time to implement it yet. It is not a hard fix I think. If you want to take a shot at it, i'm willing to help! It shouldn't be more than 20 lines of code I assume. We just need to add that extra HasForeign
instance that adds the neccesery javascript code to make a basicauth call.
Which in jQuery is:
beforeSend: function (xhr) {
xhr.setRequestHeader ("Authorization", "Basic " + btoa(username + ":" + password));
},
but finding an equivalent for axios
and angular
and plain XHR should not be hard. we just need to set the request header. We already do this for the Header
HasForeign
instance which you can look at for inspiration
Hey just wondering what the status on the issue is? I am using Generalized Authentication provided by servant-auth-server
and I am receiving the following error:
• No instance for (servant-foreign-0.11.1:Servant.Foreign.Internal.HasForeign
servant-foreign-0.11.1:Servant.Foreign.Internal.NoTypes
NoContent
(Auth auths0 AuthUser :> AdminProtected))
arising from a use of ‘writeJSForAPI’
• In the expression:
writeJSForAPI
(Proxy :: Proxy (UserAPI auths)) vanillaJS "./assets/api.js"
In an equation for ‘generateJavaScript’:
generateJavaScript
= writeJSForAPI
(Proxy :: Proxy (UserAPI auths)) vanillaJS "./assets/api.js"
Ideally I would like to use Axios instead of vanilla.
After some searching and hacking I appear to have found a solution. Creating the following instance for Auth
does the trick.
instance forall lang ftype api auths v. ( HasForeign lang ftype api
, HasForeignType lang ftype T.Text
) =>
HasForeign lang ftype (Auth auths v
:> api) where
type Foreign ftype (Auth auths v
:> api) = Foreign ftype api
foreignFor lang Proxy Proxy subR =
foreignFor lang Proxy (Proxy :: Proxy api) req
where
req = subR {_reqHeaders = HeaderArg arg : _reqHeaders subR}
arg =
Arg
{ _argName = PathSegment "Authorization"
, _argType =
typeFor lang (Proxy :: Proxy ftype) (Proxy :: Proxy T.Text)
}
Now I'm pretty new to type level programming so a lot of this is going over my head, I just found a very similar solution online and fought with compiler until the types matched up.
The only issue with this solution is the fact that it produces:
Authorization: <key>
instead of the desired Authorization: Bearer <key>
I cannot figure out what to change to achieve my desired result. My current solution is to just pass Bearer <> key
to the javascript functions, but this doesn't feel right. Any help toward a solution to this/ helping my understanding of the type level stuff would be greatly appreciated.
Also, should the above instance be included by default?
@domenkozar Is it always the case that the Authorization
header is used? Do we always want Bearer
too? And more generally, is the above code a good start for supporting the new auth stuffs in -foreign?
For reference for anyone attempting this in the future the below change is all that is needed to add Bearer
to the generated code.
req = subR {_reqHeaders = ReplaceHeaderArg arg "Bearer {Authorization}" : _reqHeaders subR}
In relation to supporting new auth stuffs in foreign:
Would it be possible to add another (optional) piece of information to the Auth
data type that would resemble the scheme of the authorization?
For example: data Auth authScheme (auths :: [*]) val
Could this authScheme
value be used to pattern match for the instances and add different behaviour? Or conversely be used a function to determine the behaviour?
I might be way off here but this would be something I would be very interested in working on if I could receive a few pointers along the way.
for basic authentication I managed to get away with this orphan instance:
instance (HasForeign lang ftype api, HasForeignType lang ftype Text) => HasForeign lang ftype (BasicAuth a b :> api) where
type Foreign ftype (BasicAuth a b :> api) = Foreign ftype api
foreignFor lang proxy1 Proxy subR = foreignFor lang proxy1 (Proxy :: Proxy api) req
where
req = subR {_reqHeaders = HeaderArg arg : _reqHeaders subR}
arg =
Arg
{ _argName = PathSegment "Authorization"
, _argType =
typeFor lang (Proxy :: Proxy ftype) (Proxy :: Proxy Text)
}
(I've never done type-level programming with Haskell, this is largely an adaptation of the code by @mcgizzle and from https://github.com/sordina/servant-options/issues/3)
writeJSForAPI
fails to type check after I addBasicAuth
to my api.