nickredmark / ooth Goto Github PK
View Code? Open in Web Editor NEWUser identity/authentication/accounts management microservice for node.js
Home Page: https://nmaro.github.io/ooth/
License: MIT License
User identity/authentication/accounts management microservice for node.js
Home Page: https://nmaro.github.io/ooth/
License: MIT License
It has been a while since I wrote an article about ooth
As far as I can tell, babel is only used at build time. Therefore all babel-related dependencies should be listed under devDependencies
Hi,
I could find the Staart project anywhere on the Internet. Please share some info about it.
Regards,
Vijayant Saini
Hi, interesting project.
In order to motivate contribution and usage of this software it would be great if you can clarify and publish what kind of licence the code is published under.
Thanks
Hi, is it possible to provide additional fields inside API response?
Currently using ooth-local login or getStatus I get response similar to this:
{"user":{"_id":"5af48ba5b91e401fb62800c6","local":{"email":"[email protected]"}}}
Is it possible to add for example permissions key to get response similar to this:
{"user":{"_id":"5af48ba5b91e401fb62800c6","local":{"email":"[email protected]","permissions":"admin"}}}
Follow-up of #6
Getting an error when I try to Reset Password after only registering in Facebook (in the example app you created). Went to the library and it looks like this isn't defined anywhere
Error is "getUniqueField is not defined"
Hi,
I am really interested on using your nextjs integration exemple with apollo, as a base for my personal projects.
I encountered 2 errors :
The first one is simply about renaming settings.dist.js to settings.js, so the import can occurs
Unfortunately I can not figure out what causes the second error :
{ Invariant Violation: Objects are not valid as a React child (found: 5923bbe80115a80a2d96abe0). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of 'LoginStatusComponent'.
at invariant (/mnt/c/Users/Elies/Workspace/next/bug/node_modules/fbjs/lib/invariant.js:44:15) at traverseAllChildrenImpl (/mnt/c/Users/Elies/Workspace/next/bug/node_modules/react-dom/lib/traverseAllChildren.js:144:56) at traverseAllChildrenImpl (/mnt/c/Users/Elies/Workspace/next/bug/node_modules/react-dom/lib/traverseAllChildren.js:93:23) at traverseAllChildren (/mnt/c/Users/Elies/Workspace/next/bug/node_modules/react-dom/lib/traverseAllChildren.js:172:10) at Object.instantiateChildren (/mnt/c/Users/Elies/Workspace/next/bug/node_modules/react-dom/lib/ReactChildReconciler.js:70:7) at ReactDOMComponent._reconcilerInstantiateChildren (/mnt/c/Users/Elies/Workspace/next/bug/node_modules/react-dom/lib/ReactMultiChild.js:187:41) at ReactDOMComponent.mountChildren (/mnt/c/Users/Elies/Workspace/next/bug/node_modules/react-dom/lib/ReactMultiChild.js:226:27) at ReactDOMComponent._createContentMarkup (/mnt/c/Users/Elies/Workspace/next/bug/node_modules/react-dom/lib/ReactDOMComponent.js:653:32) at ReactDOMComponent.mountComponent (/mnt/c/Users/Elies/Workspace/next/bug/node_modules/react-dom/lib/ReactDOMComponent.js:520:29) at Object.mountComponent (/mnt/c/Users/Elies/Workspace/next/bug/node_modules/react-dom/lib/ReactReconciler.js:46:35) name: 'Invariant Violation', framesToPop: 1 }
To reproduce it:
Thanks for help !
Edit :
I've finally figured this out,
class LoginStatusComponent extends Component {
render() {
const { oothClient, user } = this.props
if( user ) {
return (
<div>
Your user id is {user._id.toString()} // added .toString()
<button onClick={() => {
oothClient.logout()
}}>Log out
</button>
</div>
)
} else {
return <div>
Click on the button to create a guest session.<br />
<button onClick={() => {
oothClient.authenticate('guest', 'register')
.catch(err => {
console.error(err)
})
}}>Log in
</button>
</div>
}
}
}
Follow-up of #6
@nmaro , I propose to use some config package like node-config instead of present *.dist.js
things.
If confirmed I'll make a PR for this.
It looks like you are currently using a salt cost of 10. https://github.com/nmaro/ooth/blob/c400796ee0a5cd83d106f6b6dabeb93103691829/packages/ooth-local/src/index.js#L6. I believe that the current accepted default for most bcrypt libraries is 12. I would recommend either raising that default to 12, or having it be a parameter that can be passed in by the user so they can choose their own values.
I've recently come across this article https://hackernoon.com/your-node-js-authentication-tutorial-is-wrong-f1a3bf831a46 which does a pretty good job at listing the usual problems with node js authentication tutorials, and it's a good read for things to keep in mind.
This is good for mobile authentication.
Would be great to abstract out the db backend, so non-MongoDB can be used. FeatherJS is a good example of abstracting DB operations.
Follow-up of #6
Add a new strategy ooth-profile
that can't be used to log in but to manage a user's profile.
Currently the password strictness tests are not exposed and aren't configurable, such that when using ooth-local
I just have to accept that all user passwords must contain a number, a lowercase letter, an uppercase letter and be at least 6 characters long. I would prefer I could configure this myself.
hey @nmaro can you add hacktoberfest tags to issues so ooth gets some love?
Investigate the topic.
After getting everything setup and working nicely locally, I get this error (in production) when trying to hit my root /
page:
FetchError: invalid json response body at http://app-staging.field-test.co/auth/status reason: Unexpected token < in JSON at position 0
Even if I update from localhost
to <live domain>
or <live domain>:4000
in the MongoClient.connect()
function...
It seems like the logic for inserting an Ooth local user with hashed password is inside an express route, and this is the only place it exists. Because of the prerequisite of ooth-roles
that a user has to have their role set manually to admin, it seems like there's no good way to programmatically create that first user if they don't exist and give them an admin role. I could recreate the password hashing that is going on inside ooth-local
, but this seems like a really bad idea. Is there something I'm missing here?
This would be useful for typed database adaptors like mongoose or mysql.
Send an SMS with a code
When calling ooth.start
I see the error
TypeError: this.route.ws is not a function
at Ooth.start (/Users/gsferrer/Projects/myProject/node_modules/ooth/lib/index.js:211:24)
Looking at the source, it appears that expressws(app)
is called in start()
after the router has been created in the Ooth constructor.
From the express-ws README:
Important: Make sure to set up the express-ws module like above before loading or defining your routers! Otherwise, express-ws won't get a chance to set up support for Express routers, and you might run into an error along the lines of router.ws is not a function.
The current next.js solution uses ooth, api and next.js server all in one. This means that only one cookie-session is needed. But if ooth and api are separate, 3 cookie-sessions are needed, + the server needs to be able to communicate with ooth and api (on the server side probably JWTs are better). Both ooth and the next.js implementation need to be extended to support that.
I'm about to start working on a new project for which I'm going to have to setup an auth system. Given the complete lack of a full auth library setup for node, I was looking for some boilerplate code so that I didn't have to setup the whole thing from scratch and would just fix whatever security vulnerabilities it had. While I was looking for one of those I came across your project and it looks like you've been putting in a lot of work into maintaining it. I think this project might be exactly what i'm looking for. If you have time in the next few days to walk me through the project, I could create a postgres integration with the same api as your current mongo one, https://github.com/nmaro/ooth/tree/master/packages/ooth-mongo and you could add it as a package.
Ideally a documentation generator like used in Backbone Annotated source code documentation might be used. This is generated using docco.
This article makes some good security remarks: https://hackernoon.com/your-node-js-authentication-tutorial-is-wrong-f1a3bf831a46
Most Ooth and ooth plugin messages are currently hardcoded, move them i18n/en.json and make them configurable.
The Ooth public interface is slowly stable enough that it can be documented with jsdocs and a documentaion generated from it.
Hi @nmaro. What about to have programmatic API for ooth
alongside HTTP?
That will allow creating ooth
-based services that can communicate not only by HTTP, but any transporter (e.g WebSocket, RabbitMQ, NATS, etc) and with the power of any framework (e.g. seneca, moleculer, sails, koa, etc.).
In this way, current HTTP API, which is now hard tied to express, may become an express router which uses programmatic API internally.
As far of now I can't find any way to integrate ooth with some existing code base than make fetch
/request
to ooth
's HTTP endpoint, and that looks like a pretty strange (and expensive in latency) solution.
I'm trying to get graphql-api-with-auth
running. I'm using node 8.7. After running npm run start
I can't access http://localhost:3002/graphiql
or http://localhost:3002/guest/register
. I do get the error Cannot GET ...
Right now the most up-to-date example is the staart boilerplate: https://github.com/nmaro/staart
I should go through the examples in the example folder, update them and lift the package versions.
any thoughts on it?
When i'm signing, using the Facebook strategy, then log out, then sign in again, ooth creates a new account with a new userId, which, in the Facebook strategy contains the same id field as the first account. Noteworthy might be that i do not provide the email via Facebook oauth, since you can unselect it in the Facebook oauth consent screen.
The same userId should be used to sign in.
with
registerUniqueField('id', 'id');
I didn't submit a pull request though, i'm not sure if this is the intended way to fix or if there is any specific reason why registerStrategyUniqueField('id');
is used.
Thanks for a great looking library. One of the nice things Meteor had was the ability to handle authentication without cookies. I'm unclear from your docs whether this is feasible with Ooth.
The use case is React Native apps, in which authentication is commonly handled by sending a JWT with each request.
Is that possible? Could it be added to your docs if so?
hi! just trying to try out your basic ooth example. couldnt get it to start. here's what happened after npm install:
> node --harmony-async-await index.js
node: bad option: --harmony-async-await
npm ERR! Darwin 16.4.0
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "start"
npm ERR! node v6.9.4
npm ERR! npm v3.10.10
npm ERR! code ELIFECYCLE
npm ERR! [email protected] start: `node --harmony-async-await index.js`
npm ERR! Exit status 9
npm ERR!
npm ERR! Failed at the [email protected] start script 'node --harmony-async-await index.js'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the ooth-example package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! node --harmony-async-await index.js
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs ooth-example
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls ooth-example
npm ERR! There is likely additional logging output above.
i am on node 6.9.4 and from googling this harmony-async-await problem it looks like node 7 is required. however it is not the active version of node. is this a required dependency?
First I wanna say ty for starting this project. Following the integrated example, I made the curl request:
curl -XPOST http://localhost:3002/auth/guest/register
and the response is missing the token:
{"user":{"_id":"5a0bf5d9280f3c24fe626322"}}
For the response to includes the token I have to pass in standalone: true
here https://github.com/nmaro/ooth/blob/master/examples/integrated/api/ooth.js#L11
I think it's confusing because standalone implying running ooth as a standalone server & I have to pass in standalone: true
for the integrated example to work.
Going through the code, it looks like the only thing standalone config does is including the token in the response? I think you could remove the standalone config altogether & return the token in the response header by default.
/status
should works with the token as well?
Thanks for a great looking project. Reading your docs, it looks like you're oriented towards establishing a session with an API using a cookie, whether standalone or integrated, after obtaining a JWT via ooth to show authentication status.
However:
ooth
for sessionless authentication.Non expiring JWT vulnerability
Looking at the ooth
module, a non-expiring JWT is issued in exchange for a valid login. This means you can never log out a user - if they have the JWT, they can always pass it to the API for use, and it will be valid. Unless the API tracks a JWT blacklist, it will be unable to block malicious users. Tracking a blacklist means database calls, and the point of JWTs is to prove authentication without database access.
ooth/src/index.js:319:
getToken(user) {
return sign({ user }, this.sharedSecret);
}
I think it would be preferable to use short lived JWTs. This ensures that creating a session with the API can only be done for a limited amount of time. The session cookie can be as long as the API wishes.
The JWT expiry can be set as an exp
field as observed by Passport
.
getToken(user) {
return sign({
user,
exp: ...some time in the future
}, this.sharedSecret);
}
Enabling sessionless JWT authentication with refresh tokens
There's a significant use case of authenticating every API request with a JWT, instead of a cookie based session. This is the typical authentication method used in mobile apps, eg React Native. For this use case, if JWTs are to have an expiry, a method must be provided to obtain new JWTs without logging in every time.
A refresh token is typically used: https://www.jaygould.co.uk/dev/2017/07/18/jwt-token-refresh-redux-react-native.html
In short, using the refresh token causes a database check to ensure:
The UI experience for the user is the same, but with more security:
It seems this would be handy for many and will increase security.
JWT size/single concern contents
A disadvantage to using the ooth
JWT token for authenticating all requests is that the ooth
use does not quite adhere to the JWT spec....they are mean to be compact.
Ooth
places the user profile uniqueFields
information into the JWT. Okayish if the JWT is just used once to send to an API to establish a cookie-based session. But sending a large JWT token for every request becomes a problem when the user profile is large - eg Facebook data.
For instance, when logging in with the local
strategy, the JWT token provided on login contains:
{
user: {
_id: <user id>,
local: {
username: undefined,
email: <user email>,
verified: undefined
}
}
}
The JWT is being used to transfer user data, rather than the single concern of authentication status. This mix of concerns is reflected in the response body, which has both a user field, containing the same information as encoded in the token field.
The minimal, single-concern JWT token implementation would be to only place the user _id
(and perhaps as a future feature authorisation data such as roles or similar) into the JWT. The fact of having a valid JWT with that user id means that authentication has occurred. If the API needs more user data, it can always access the database.
This is how Meteor approaches tokens - a resumeToken
isn't even a JWT; it's simply a random string which optionally expires, see line 589. Holding the resumeToken
signifies only that the user was authenticated; the token itself contains no data.
Minimal JWT:
{
_id: <user id>,
exp: <UNIX time in future>,
iat: <UNIX time of issue>
}
Naturally, it's still very handy/essential for each strategy to administer profile fields. They can still be provided in the user
field of the response body, or accessed by an API from the database.
Happy to potter along with a PR(s) to address these issues, but would be great to get thoughts before starting.
Create an intro video on youtube (btw my channel is https://www.youtube.com/channel/UC8hFeDN1h9Xk0SqeOgiwSlw)
It would show the power of ooth to show it can be integrated with RAN
Good morning. Ooth is a great idea. Save me tons of time already.
I found a couple of minor issues related to the user verification in the ooth-local.
There is a PR https://github.com/nmaro/ooth/pull/20/files for review. I made an effort to stay with consistent with you code format, but if you see any issues, just leave me a comment.
If this PR is of no use to you, just close it out, no worries.
Have a good one and thanks for working on this critical library.
P
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.