Open brillout opened 4 years ago
@Johnson444 We can implement this together, if that's something you'd be interested in doing. I've cleaned up the source code, it's now all TypeScript, and test coverage is close to 100% which makes developing super comfy.
https://github.com/reframejs/wildcard-api/pull/58#issuecomment-711412477
I'm curious, you mentioned a while ago using
getContext
to set cookies, are you still using that approach? What do you think of #59?
I'm only using it in a small inactive pet project, but yes. Besides putting data in the context from Express, I'm also putting functions in it. It works fine. I think it's nicer to assign the those functions to the context than to the server
object. If you read the code you would think the functions are provided by the library, because server
is imported from the library.
I would prefer to move Wildcard sessions to its own plugin/library, because I would prefer to handle those things myself, although it's definitely a nice idea to showcase Wildcard and have some authentication running quickly.
The plan is to actually integrate this with an interface that could eventually become a public API. For now the interface would be private but you're right maybe it should be exposed right at the beginning.
I think it's nicer to assign the those functions to the context than to the server object.
Interesting. So basically you prefer to define server endpoints dynamically on each API request, is that correct? Personally, I find it simpler to reason about static functions + a context object. But maybe you are seeing something I'm not seeing.
I think it's nicer to assign the those functions to the context than to the server object.
Interesting. So basically you prefer to define server endpoints dynamically on each API request, is that correct? Personally, I find it simpler to reason about static functions + a context object. But maybe you are seeing something I'm not seeing.
No, with "those" functions I don't mean the endpoint functions, but the helper functions to interact with Express, like setCookies()
or getHeaders()
.
The getApiHttpResponse()
function could be used to control the context:
import express from "express";
import { getApiHttpResponse } from '@wildcard-api/server';
const app = express();
app.all('/_wildcard_api/*', async (req, res) => {
const context = {
user: getAuthUser(req.headers),
};
const {url, method, body} = req;
const {httpResponse, endpointResult, endpointName} = await getApiHttpResponse({url, method, body}, context);
if( endpointName==='login' && endpointResult.success ){
setCookies(req, endpointResult.user);
}
// `httpResponse` contains the HTTP encoded equivalent of `endpointResult`
res.status = httpResponse.statusCode;
res.type = httpResponse.contentType;
res.send(httpResponse.body);
});
This gives full control over to the user.
@michie1 Would that work for you?
I would prefer to handle those things myself
Why? Are you using an Express middleware that does this for you?
@michie1 Would that work for you?
I would prefer to handle those things myself
Why? Are you using an Express middleware that does this for you?
Different applications need different types of authentication. I think it's better if Wildcard is providing an authentication option (as a plugin) and not enforcing anything. I'm using my own Express middleware function that puts helper functions in the context object.
Wildcard Sessions will be optional and you'll have more control over the context/auth than what currently is the case.
I'm using my own Express middleware
Can you imagine yourself removing your custom Express middleware and use Wildcard Sessions instead? If not, why not? You said you prefer to handle these things yourself and I'm left to wonder why :-).
Wildcard Sessions will be optional and you'll have more control over the context/auth than what currently is the case.
Cool.
I'm using my own Express middleware
Can you imagine yourself removing your custom Express middleware and use Wildcard Sessions instead? If not, why not? You said you prefer to handle these things yourself and I'm left to wonder why :-).
Well, I might use it for simple applications, but like I said, different applications need different type of authentication. Maybe I don't want to use a password for authentication, but I want have an login link send by email, use 2FA or SSO. It's difficult to compare wildcard sessions that is not there yet versus all the other existing options.
Wildcard Sessions only does session management; you can use it with any auth strategy:
// Username + password
server.login = function(username, password) {
if (await invalidCredentials(username, password)) return;
this.user = { username }; // Wildcard will automatically persist `this.user` by using HTTP cookies
};
// OAuth
server.oauthCallback = function(userProfile) {
// At the end of the OAuth flow, we save the user information to the context object
this.user = userProfile; // Wildcard will automatically persist `this.user` by using HTTP cookies
};
// Etc.
Instead of dealing with cookies you simply deal with reading/writing the context object.
I would suggest that if you're looking to check the authenticity of the cookie, a library like https://npm.im/@hapi/iron is the gold standard for this sort of thing. I see that my colleagues at Auth0 reach for this library for similar uses-cases.
I would suggest that if you're looking to check the authenticity of the cookie, a library like https://npm.im/@hapi/iron is the gold standard for this sort of thing. I see that my colleagues at Auth0 reach for this library for similar uses-cases.
Thanks for the pointer. Wildcard is using HMAC-SHA256 which is old, battle-tested, and assailed against by researchers. So we should be good here.
The idea is to allow the server to modify the context:
~ EDIT ~What happens here is that Wildcard sets a first cookie with the value of
this.user
and a second cookie with a signature.The signature ensures that the cookie was set by the server.
Wildcard sessions can be used to easily implement any auth strategy:
I've already implemented a first prototype which I'm currently using in production.