{"id":16344185,"url":"https://github.com/breuerfelix/react-graphql-authentication","last_synced_at":"2026-04-13T17:04:09.673Z","repository":{"id":141131992,"uuid":"135400256","full_name":"breuerfelix/react-graphql-authentication","owner":"breuerfelix","description":"Authentication with reactJs, ExpressJs, GraphQL, MobX and Bulma.io","archived":false,"fork":false,"pushed_at":"2024-02-22T17:43:13.000Z","size":1441,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-09T22:19:23.273Z","etag":null,"topics":["authentication","bulma","graphql","jwt-authentication","react"],"latest_commit_sha":null,"homepage":"https://breuer.dev/blog/react-graphql-auth","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/breuerfelix.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-05-30T06:48:16.000Z","updated_at":"2024-02-22T17:44:17.000Z","dependencies_parsed_at":"2024-02-22T18:57:07.028Z","dependency_job_id":null,"html_url":"https://github.com/breuerfelix/react-graphql-authentication","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/breuerfelix%2Freact-graphql-authentication","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/breuerfelix%2Freact-graphql-authentication/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/breuerfelix%2Freact-graphql-authentication/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/breuerfelix%2Freact-graphql-authentication/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/breuerfelix","download_url":"https://codeload.github.com/breuerfelix/react-graphql-authentication/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247176001,"owners_count":20896384,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","bulma","graphql","jwt-authentication","react"],"created_at":"2024-10-11T00:27:11.753Z","updated_at":"2026-04-13T17:04:09.634Z","avatar_url":"https://github.com/breuerfelix.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React / GraphQL Authentication\n\nThis project is about me learning a Javascript framework called [React](https://reactjs.org) and [GraphQL](https://graphql.org). Like always, it's easier to learn new stuff when applying it to a project.  \nI decided to create a simple authentication system.\n\nThe theme is made with [Bulma.io](https://bulma.io) because I wanted to try out a popular alternitive to [Bootstrap](https://getbootstrap.com). The docmentation for Bulma is also really good.\n\nFor saving the login credentials I used [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken).\n\n## Database\n\nTo store all the user data I use a simple json file based database called [lowdb](https://github.com/typicode/lowdb). I didn't want to install a local DB only for a little project.  \nEven though I implemented all database actions in a seperate class. It would be kinda easy to refactor the database to MySQL only by changing this class. All other code still behave the same.\n\nPasswords are also stored in a hashed format to increase security. This is done via [bcrypt](https://www.npmjs.com/package/bcrypt).\n\n### Class snippet\n\n```js\nimport low from 'lowdb';\nimport FileSync from 'lowdb/adapters/FileSync';\n\nconst adapter = new FileSync('./databaseUser.json');\nconst userLow = low(adapter);\n\nuserLow.defaults({ users: [] }).write();\n\nclass userDB {\n    async getUserByEmail(email) {\n        return userLow\n            .get('users')\n            .find({ email })\n            .value();\n    }\n\n    async updateToken(username, token) {\n        return userLow\n            .get('users')\n            .find({ username })\n            .set('iat', jwt.decode(token).iat)\n            .write();\n    }\n}\n```\n\n### File preview\n\n```json\n{\n    \"users\": [\n        {\n            \"username\": \"test\",\n            \"password\":\n                \"$2b$10$L72HnDgRvpS9N87iuTdZcewJMNmNFeep21HCgnFU0hv6b/FoXI36.\",\n            \"email\": \"test@test.de\",\n            \"iat\": 1528578690\n        }\n    ]\n}\n```\n\n## API\n\nWhile searching the web for an alternative to Axios with Express, I learned about GraphQL. This API should fit nice into React.  \nAt the beginning it was kinda hard to learn, because it works really different to other API's out there.\n\nAfter setting my application up for handling GraphQL, the steps were gettin easier and faster along the way. Implementing more and more requests were faster after the core work was done.\n\n### GraphQL snippet\n\n```js\nconst typeDef = gql`\n    type User {\n        username: String\n        email: String\n        jwt: String\n    }\n    type Mutation {\n        usernameExists(username: String!): Boolean\n        emailExists(email: String!): Boolean\n        passwordCorrect(username: String!, password: String!): Boolean\n        login(username: String!, password: String!): User\n        signup(username: String!, email: String!, password: String!): Boolean\n        verifyToken(token: String!): User\n    }\n`;\n\nconst resolver = {\n    Mutation: {\n        usernameExists: async (obj, { username }) =\u003e {\n            return await checkUsername(username);\n        },\n        emailExists: async (obj, { email }) =\u003e {\n            return await userDB.getUserByEmail(email);\n        },\n        passwordCorrect: async (obj, { username, password }) =\u003e {\n            return await checkPassword(username, password);\n        },\n        login: async (root, { username, password }, context) =\u003e {\n            const user = await checkUsername(username);\n\n            if (user) {\n                const checkedPassword = await checkPassword(username, password);\n                if (checkedPassword) {\n                    const token = jwt.sign(\n                        {\n                            username\n                        },\n                        config.jwtSecret\n                    );\n\n                    const u = await userDB.updateToken(username, token);\n\n                    return { username: u.username, email: u.email, jwt: token };\n                } else {\n                    throw new Error('Password is incorrect!');\n                }\n            } else {\n                throw new Error('Username does not exist!');\n            }\n        },\n        signup: async (obj, { username, email, password }) =\u003e {\n            return await userDB.addUser(username, email, password);\n        },\n        verifyToken: async (obj, { token }) =\u003e {\n            try {\n                const decoded = jwt.decode(token);\n                const user = await userDB.getUser(decoded.username);\n                if (user) {\n                    if (user.iat === decoded.iat) {\n                        return { username: user.username, email: user.email };\n                    } else {\n                        return null;\n                    }\n                } else {\n                    return null;\n                }\n            } catch (err) {\n                return null;\n            }\n        }\n    }\n};\n```\n\n## State Management\n\nFor state management of react applications many people use [ReduxJs](https://redux.js.org). I thought this is really complex because you have to pass everything to the props of your components. Sometimes this gets really annoying when adding some functions to your state.  \nYou always have to make sure to pass them correctly to every component which needs to access this function.\n\nAfter searching the web I learned about [MobX](https://mobx.js.org). I used Webpack to write ES6 code anyways, so I added another plugin to allow decorators in my javascript files. This function is really handy because MobX comes with alot of nice and easy to handly decorators.\n\nEvery component which needs to access one specific state, just needs to get it inserted via decorators.  \nIn my opinion the code looks way cleaner and easier to read.\n\n### User State snippet\n\n```js\nclass userStore {\n    @observable username = '';\n    @observable email = '';\n\n    @observable isAuthenticated = false;\n\n    @action\n    login(username, email, token) {\n        localStorage.jwtToken = token;\n\n        this.username = username;\n        this.email = email;\n        this.isAuthenticated = true;\n    }\n\n    @action\n    logout() {\n        if (localStorage.jwtToken) {\n            delete localStorage.jwtToken;\n        }\n\n        this.isAuthenticated = false;\n        this.username = '';\n        this.email = '';\n\n        client.resetStore();\n\n        history.push('/');\n    }\n}\n```\n\n### Example observer / injection\n\n```js\n@observer\n@inject('userStore')\nclass LoginHeader extends React.Component {\n    constructor(props) {\n        super(props);\n        this.state = {\n            username: '',\n            password: '',\n            isLoading: false,\n            errorUsername: false,\n            errorPassword: false,\n            signup: false\n        };\n    }\n}\n```\n\n## Screenshots\n\n### Navbar\n\n![navbar](assets/navbar.png)\n\n### Logged in\n\n![personal](assets/personal.png)\n\n### Signup modal\n\n![signup](assets/signup.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbreuerfelix%2Freact-graphql-authentication","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbreuerfelix%2Freact-graphql-authentication","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbreuerfelix%2Freact-graphql-authentication/lists"}