{"id":15287543,"url":"https://github.com/42bv/redux-mad-authentication","last_synced_at":"2025-04-13T05:35:11.603Z","repository":{"id":19836855,"uuid":"88037078","full_name":"42BV/redux-mad-authentication","owner":"42BV","description":"A library which stores login credentials in Redux to allow a user to login to a Spring Boot application.","archived":false,"fork":false,"pushed_at":"2023-01-03T15:15:13.000Z","size":1035,"stargazers_count":3,"open_issues_count":15,"forks_count":1,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-04-13T05:33:59.750Z","etag":null,"topics":["authentication","fetch","login","logout","redux","spring-mvc","spring-security","xsrf"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/42BV.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-04-12T09:57:27.000Z","updated_at":"2019-05-17T08:25:28.000Z","dependencies_parsed_at":"2023-01-13T20:37:24.216Z","dependency_job_id":null,"html_url":"https://github.com/42BV/redux-mad-authentication","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/42BV%2Fredux-mad-authentication","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/42BV%2Fredux-mad-authentication/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/42BV%2Fredux-mad-authentication/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/42BV%2Fredux-mad-authentication/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/42BV","download_url":"https://codeload.github.com/42BV/redux-mad-authentication/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248670509,"owners_count":21142896,"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","fetch","login","logout","redux","spring-mvc","spring-security","xsrf"],"created_at":"2024-09-30T15:30:43.387Z","updated_at":"2025-04-13T05:35:11.570Z","avatar_url":"https://github.com/42BV.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# About\n\n[![Build Status](https://travis-ci.org/42BV/redux-mad-authentication.svg?branch=master)](https://travis-ci.org/42BV/redux-mad-authentication)\n[![Codecov](https://codecov.io/gh/42BV/redux-mad-authentication/branch/master/graph/badge.svg)](https://codecov.io/gh/42BV/redux-mad-authentication)\n\nThis is 42's authentication module for Redux in combination with\na specific Spring Security settings.\n\nIt can do the following things:\n\n  1. Log the user in and out with your Spring application.\n  2. Saving the current user in the Redux store.\n  3. Send 'fetch' request with XSRF tokens and the cookies.\n  4. Make a route only available for logged in users.\n  5. Make a route available for specific users, based on properties\n     of the current user.\n\n# Getting started.\n\nWe assume you have a working Redux project, if you do not yet have\nRedux add Redux to your project by following the Redux's instructions.\n\nFirst install the following dependencies in the package.json:\n\n  1. \"react-redux\": \"5.0.3\",\n  2. \"redux\": \"3.6.0\",\n  3. \"react-router-dom\": \"4.0.0\"\n\nNow add the authentication-reducer to your rootReducer for example:\n\n```js\nimport { combineReducers } from 'redux';\nimport { authentication, AuthenticationStore } from 'redux-mad-authentication';\n\nexport interface Store {\n  authentication: AuthenticationStore\n};\n\n// Use ES6 object literal shorthand syntax to define the object shape\nconst rootReducer: Store = combineReducers({\n  authentication,\n});\n\nexport default rootReducer;\n```\n\nThis should add the AuthenticationStore to Redux, which will store\nthe logged in user.\n\nNext you have to configure the authentication module:\n\n```js\nimport { createStore } from 'redux';\nimport { configureAuthentication } from 'redux-mad-authentication';\n\nexport const store = createStore(\n  rootReducer,\n);\n\nconfigureAuthentication({\n  // The URL of your Spring back-end where the user can login (POST) and logout(DELETE)\n  authenticationUrl: '/api/authentication',\n\n  // The URL of your Spring back-end where the current user can be requested via GET\n  currentUserUrl: '/api/authentication/current',\n\n  // The route (in the front-end) the user should be redirected to when not logged in.\n  loginRoute: '/login',\n\n  // A reference to the dispatch function for the react store.\n  dispatch: store.dispatch,\n\n  // A function which returns the current 'authentication' store \n  authenticationStore: () =\u003e store.getState().authentication\n});\n```\n\nThe authentication module must be configured before the application\nis rendered.\n\n# How to\n\n## Writing a LoginForm.\n\nIn order to log the user in you must have a login form of some sorts.\nThis library does not assume anything on how this login form should\nwork or what it looks like.\n\nHere's what a LoginForm should do:\n\n  1. Call 'login' when the user submits the login form, with the correct body.\n  2. Try to auto-login the user via `current` in the componentDidMount.\n  3. In the `render` Redirect the user when he is logged in.\n\nFor example:\n\n```js\nimport React, { Component } from 'react';\nimport { connect } from 'react-redux';\nimport { Redirect, locationShape } from 'react-router-dom';\nimport { login, current } from 'redux-mad-authentication';\n\nimport { Store } from '../redux/root-reducer';\n\ninterface Props {\n  loggedIn: boolean,\n  location: locationShape\n};\n\ninterface State {\n  username: string,\n  password: string,\n  error: boolean,\n  autoLoginFailed: boolean\n};\n\nexport class Login extends Component\u003cProps, State\u003e {\n  state = {\n    username: '',\n    password: '',\n    error: false,\n    autoLoginFailed: false\n  };\n\n  // Calling `current()` automatically logs the user in when the session is still valid\n  componentDidMount() {\n    current().catch(() =\u003e {\n      this.setState({ autoLoginFailed: true });\n    });\n  }\n\n  onSubmit(event: Event) {\n    event.preventDefault();\n\n    const { username, password } = this.state;\n\n    this.setState({ error: false });\n\n    // `login` expects a body to send to the server\n    login({  username, password }).catch((error) =\u003e {\n      this.setState({ error: true });\n    });\n  }\n\n  setUsername(username: string) {\n    this.setState({ username });\n  }\n\n  setPassword(password: string) {\n    this.setState({ password });\n  }\n\n  render() {\n    // Be sure \n    if (this.props.loggedIn) {\n      const { from } = this.props.location.state || { from: { pathname: '/' } };\n\n      return \u003cRedirect to={ from }/\u003e;\n    }\n\n    if (this.state.autoLoginFailed === false) {\n      return null;\n    }\n\n    const { username, password, error } = this.state;\n\n    const errorMessage = error ? 'Username and password are incorrect' : '';\n\n    return (\n      \u003cform\u003e\n        \u003ch1\u003ePlease log in\u003c/h1\u003e\n        \u003cp\u003e\n          \u003clabel htmlFor=\"username\"\u003eUsername\u003c/label\u003e\n          \u003cinput\n            id=\"username\"\n            name=\"username\"\n            type=\"text\"\n            value={ username }\n            onChange={ (event) =\u003e this.setUsername(event.target.value) }\n          /\u003e\n        \u003c/p\u003e\n\n        \u003cp\u003e\n          \u003clabel htmlFor=\"password\"\u003ePassword\u003c/label\u003e\n          \u003cinput\n            id=\"password\"\n            name=\"password\"\n            type=\"password\"\n            value={ password }\n            onChange={ (event) =\u003e this.setPassword(event.target.value) }\n          /\u003e\n        \u003c/p\u003e\n\n        \u003cp\u003e{ errorMessage }\u003c/p\u003e\n\n        \u003cbutton type=\"sumbit\" onClick={ (event) =\u003e this.onSubmit(event) }\u003eLog in\u003c/button\u003e\n      \u003c/form\u003e\n    );\n  }\n}\n\nexport default connect((store: Store) =\u003e {\n  return {\n    loggedIn: store.authentication.isLoggedIn\n  };\n})(Login);\n```\n\n## Writing a Logout\n\nIn order to logout you must call the 'logout' function, and make\nsure you Redirect the user to the login form when the user is\nlogged in.\n\nFor example:\n\n```js\nimport React, { Component } from 'react';\n\nimport { connect } from 'react-redux';\nimport { Redirect } from 'react-router-dom';\nimport { Store } from '.redux/root-reducer';\nimport { logout } from 'redux-mad-authentication';\n\ninterface Props {\n  isLoggedIn: boolean\n};\n\nexport class Logout extends Component\u003cProps, void\u003e {\n\n  onLogoutClick() {\n    logout();\n  }\n\n  render() {\n    if (this.props.isLoggedIn === false) {\n      return \u003cRedirect to=\"/\"/\u003e;\n    }\n\n    return (\n      \u003ca onClick={ () =\u003e this.onLogoutClick() }\u003eUitloggen\u003c/a\u003e\n    );\n  }\n}\n\nexport default connect((store: Store) =\u003e {\n  return {\n    isLoggedIn: store.authentication.isLoggedIn\n  };\n})(Logout);\n```\n\n## Make a Route private\n\nSome routes can only be accessible when the user is logged in.\nYou can do this via the PrivateRoute for example:\n\n```js\n\u003cBrowserRouter history={ browserHistory }\u003e\n  \u003cdiv\u003e\n    \u003cRoute exact path=\"/\" component={ Dashboard } /\u003e\n    \u003cRoute path=\"/login\" component={ Login }/\u003e\n    \u003cPrivateRoute path=\"/users\" component={ Users } /\u003e\n  \u003c/div\u003e\n\u003c/BrowserRouter\u003e\n```\n\nPrivateRoute works exacly like Route, except that it does not\nsupport a `render` method. You must always provide a Component\ninstead.\n\nWhen the user tries to go to a PrivateRoute he will be redirected\nto the Config's route `loginRoute`.\n\n## Add authorization to a Route\n\nSome routes can only be accessed by a type of user or a specific\nuser. You can do this via the AuthorizedRoute.\n\n```js\n\u003cBrowserRouter\u003e\n  \u003cdiv\u003e\n    \u003cRoute exact path=\"/\" component={ Dashboard } /\u003e\n    \u003cRoute path=\"/login\" component={ Login }/\u003e\n    \u003cPrivateRoute path=\"/users\" component={ Users } /\u003e\n    \u003cAuthorizedRoute \n      path=\"/pictures\" \n      component={ Pictures }\n      authorizer={ (authenticationStore: AuthenticationStore) =\u003e {\n        return authenticationStore.currentUser.role === 'ADMIN';\n      }}\n    /\u003e\n  \u003c/div\u003e\n\u003c/BrowserRouter\u003e\n```\n\nThe authorizer function is only ran if the user is logged in.\nThe authorizer is given the authenticationStore as the first\nparameter, and is expected to return a boolean.\n\nAuthorizedRoute works exacly like Route, except that it does not\nsupport a `render` method. You must always provide a Component\ninstead.\n\nWhen the user tries to go to a AuthorizedRoute he will be redirected\nto the Config's route `loginRoute`.\n\n## Get the current user's info / login status\n\nLets say you have a component which must render the current user's\nname, you will then need the current user from the Redux store.\n\nWe can use react-redux's connect to achieve this.\n\nFor example:\n\n```js\n\nimport { connect } from 'react-redux';\nimport { Store } from '.redux/root-reducer';\n\nfunction User(props) {\n  if (isLoggedIn) {\n    return \u003ch1\u003eHi {{ props.currentUser.name }}\u003c/h1\u003e\n  } else {\n    return \u003ch1\u003ePlease log in\u003c/h1\u003e\n  }\n}\n\nexport default connect((store: Store) =\u003e {\n  return {\n    isLoggedIn: store.authentication.isLoggedIn,\n    currentUser: store.authentication.currentUser\n  };\n})(User);\n\n```\n\n## Send a request with the XSRF token as the current user.\n\nTo perform request with the XSRF token and with the cookies from\nthe current user. You can use the 'authFetch' utility from this\nlibrary:\n\n```js\n\nimport 'authFetch' from './authentication'\n\nfunction getUser() {\n  authFetch('/user/1').then((response) =\u003e {\n    console.log(response);\n  });\n}\n\n```\n\n`authFetch` is a thin wrapper around `fetch`, it only adds the\ncredentials and XSRF token, so it has the exact same arguments\nas `fetch`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F42bv%2Fredux-mad-authentication","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F42bv%2Fredux-mad-authentication","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F42bv%2Fredux-mad-authentication/lists"}