Closed AlexanderArvidsson closed 7 years ago
After hooks run after the database call happened and let you modify what is returned to the client not what gets put into the database. If you want to change the data that are being saved you have to register a before
create hook and modify hook.data
. For more examples on this, have a look at the hooks API page.
Hm, okay, seems like I misunderstood something from the examples I've looked at. Should have thought about that, though.
One question though; if the JWT access token is not stored in the database, how does feathers authenticate against it?
Also, how do I store the access token on the client in localStorage or something similar? I am using passport-steam
to login using steam credentials which doesn't give me a JWT access token, so I assumed I had to generate my own.
This is what I've set up with passport right now. What I don't understand is how the access token gets stored, both on the client and on the server. Once I sign in, the user is created / updated, but there's never any access token in cookies or localStorage, and not in the server database either. So, my question is, how do I authenticate after I have signed in through steam?
app.passport.use(
new SteamStrategy({
returnURL: 'http://localhost:3030/auth/steam/return',
realm: 'http://localhost:3030/',
apiKey: '<apikey>'
},
function(identifier, profile, done) {
const query = { steamId: profile.id };
const data = { identifier, profile };
app.service('users').find({ query })
.then(user => user.total > 0 ? updateUser(user.data[0], data) : createUser(data))
.then(user => {
done(null, user);
});
}));
app.get('/auth/steam', authentication.express.authenticate('steam'));
app.get('/auth/steam/return',
authentication.express.authenticate('steam', { failureRedirect: '/login' }),
function(req, res) {
// Successful authentication, redirect home.
res.redirect('/');
});
One question though; if the JWT access token is not stored in the database, how does feathers authenticate against it?
The JWT contains a payload, a signature, and an expiration. Check out https://jwt.io to see the internals color coded. It's really helpful.
I also think you should look into feathers-authentication oauth2 (with the passport-steam strategy).
Using it together with Feathers on the client all the JWT issuing, consuming and storing int localstorage will be done for you automatically already.
I assumed passport-steam didn't work with the OAuth2 package because it's OpenID rather than OAuth2? Are you saying it works fine with it?
I'm pretty sure it works.
Alright, I've hooked up the steam strategy to the oauth2 service.
First of all, the package requires a clientID and a clientSecret, but passport-steam
does not require any of those (only apiKey
).
After I sign in and get redirected back to returnURL
, I am met with a RethinkDB query error:
r.db("feather_test").table("users").filter(function(var_3) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
return r.expr({}).and(var_3("steamId").eq(undefined))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}).limit(1)
^^
error: ReqlRuntimeError
at Function.Term.run (E:\Development\FeathersJS\meta-drm\node_modules\rethinkdbdash\lib\term.js:43:17)
at Function.Term.then (E:\Development\FeathersJS\meta-drm\node_modules\rethinkdbdash\lib\term.js:2876:15)
at process._tickCallback (internal/process/next_tick.js:109:7)
error: Unhandled Rejection at: Promise Promise {
<rejected> TypeError: done is not a function
at E:\Development\FeathersJS\meta-drm\node_modules\feathers-authentication-oauth2\lib\verifier.js:139:24 } TypeError: done is not a function
at E:\Development\FeathersJS\meta-drm\node_modules\feathers-authentication-oauth2\lib\verifier.js:139:24
The service is set up like this
app.configure(oauth2({
name: 'steam',
Strategy: SteamStrategy,
clientID: 'not needed',
clientSecret: 'not needed',
apiKey: '<steam api key>',
returnURL: 'http://localhost:3030/auth/steam/callback',
}));
OpenID requires a returnURL, not callbackURL as the oauth2 service specifies by default.
Switching to feathers-memory
rather than RethinkDB service gives me this error:
error: Unhandled Rejection at: Promise Promise {
<rejected> TypeError: done is not a function
at E:\Development\FeathersJS\meta-drm\node_modules\feathers-authentication-oauth2\lib\verifier.js:139:24
at process._tickCallback (internal/process/next_tick.js:109:7) } TypeError: done is not a function
at E:\Development\FeathersJS\meta-drm\node_modules\feathers-authentication-oauth2\lib\verifier.js:139:24
at process._tickCallback (internal/process/next_tick.js:109:7)
Apologize that this issue has kind of been everywhere by now, I'm simply trying to get into the whole feathers.js mindset.
Maybe this issue will help: https://github.com/feathersjs/feathers-authentication/issues/154
That's the exact issue that I looked at to write the initial code, the one that didn't give me a JWT token and didn't use oauth2. Are you telling me to switch back, again?
Nope. I just remembered seeing it and I'm trying to help while I do other things. ;)
The reason the oauth2 verifier fails with this is partly due to the SteamStrategy not returning OAuth2 tokens. See: https://github.com/liamcurry/passport-steam/blob/master/lib/passport-steam/strategy.js#L103 https://github.com/feathersjs/feathers-authentication-oauth2/blob/master/src/verifier.js#L74
OAuth2 expects the strategy to get the params req, accessToken, refreshToken, profile, done
, while passport-steam
passes req, identity, profile, done
instead.
From what I can tell, using the oauth2 package won't work for me. As such, I need to do it manually like I did previously. So the question falls back to what it was previously: How do I get a JWT token from passport, and how do I store it (both on server and client).
You can probably solve this by customizing the verifier since it gets passed the same params as the callback.
Oh yeah, I remember reading that page. I totally disregarded the fact that I could customize the verifier. Will try this, thanks!
Alright, I have configured the oauth2 package with a custom verifier and the login is now successful. The users are updated/patched whenever you sign in. However, the client still tells me
{
"name": "NotAuthenticated",
"message": "Could not find stored JWT and no authentication strategy was given",
"code": 401,
"className": "not-authenticated",
"errors": {}
}
app.configure(auth());
app.authenticate()
.then(response => {
console.info('Feathers Client has Authenticated with the JWT access token!');
console.log(response);
})
.catch(error => {
console.info('We have not logged in with OAuth, yet. This means there\'s no cookie storing the accessToken. As a result, feathersClient.authenticate() failed.');
console.log(error);
});
Issue solved, I was not pointing my returnURL to the right location.
Should be /auth/steam/callback
rather than /auth/steam/return
. Oops.
Thanks for the help, though!
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue with a link to this issue for related bugs.
First of all, I am new to feathers and I may be doing something wrong, but as far as my research tells me, it should be fine.
I am trying to assign a JWT token to registered users, but when I check the database afterwards the token is not there. I'm using
feathers-rethinkdb
at the moment, but usingfeathers-memory
yields the same result.Also, when using RethinkDB, the after hook runs twice (Probably the same issue as feathersjs/feathers-rethinkdb#80), but this is unrelated to my current issue.