Let’s implement a whole authentication mechanism in React & Redux with sign up, sign in, password reset, change password and sign out in TypeScript.
🍣 GitHub Repository Whole files of this tutorial are as follows:
https://github.com/morizyun/react-redux-typescript-firebase-auth 
🐡 Get Firebase App info 
It will be needs for using Firebase authentication.
🐝 create-react-app with Redux and TypeScript You can install create-react-app   on command line:
yarn global add create-react-app  create-react-app react-ts-firebase-auth --scripts-version=react-scripts-ts cd  react-ts-firebase-authyarn add firebase react-router-dom redux react-redux recompose yarn add --dev @types/react-router @types/react-router-dom @types/react-redux @types/recompose 
 
After then, you can run app process by yarn start on terminal and open http://localhost:3000.
Also, please create some directories:
 😸 Configuration Please change tslint.json to add as follows:
{ +  "rules": { +    "jsx-no-lambda": false +  } } 
 
 🍮 Rebuild folders mkdir src/components mkdir src/components/Account mkdir src/components/App mkdir src/components/Home mkdir src/components/Landing mkdir src/components/Navigation mkdir src/components/PasswordChange mkdir src/components/PasswordForget mkdir src/components/Session mkdir src/components/SignIn mkdir src/components/SignOut mkdir src/components/SignUp mkdir src/constants mkdir src/firebase mkdir src/reducers mkdir src/store mv src/components/App.ts src/components/App/index.ts rm src/logo.svg rm src/App.test.ts rm src/App.css 
 
🐞 index Create src/index.ts file:
import  * as  React from  "react" ;import  * as  ReactDOM from  "react-dom" ;import  { Provider } from  "react-redux" ;import  { App } from  "./components/App" ;import  "./index.css" ;import  registerServiceWorker from  "./registerServiceWorker" ;import  { store } from  "./store" ;ReactDOM.render(           </Provider>,    document.getElementById("root") ); registerServiceWorker(); 
 
🚕 Constants Add src/constants/routes.ts file:
export  const  SIGN_UP = "/signup" ;export  const  SIGN_IN = "/signin" ;export  const  LANDING = "/" ;export  const  HOME = "/home" ;export  const  ACCOUNT = "/account" ;export  const  PASSWORD_FORGET = "/password_forget" ;
 
🐯 Components Account Create src/components/Account/index.tsx file:
import  * as  React from  "react" ;import  { connect } from  "react-redux" ;import  { compose } from  "recompose" ;import  { withRouter } from  'react-router-dom' import  { PasswordChangeForm } from  "../PasswordChange" ;import  { PasswordForgetForm } from  "../PasswordForget/PasswordForgetForm" ;import  { withAuthorization } from  "../Session/withAuthorization" ;const  AccountComponent = ({ authUser }: any  ) =>  (  
     Account: {authUser.email}</h1>       >         </div>  ); const mapStateToProps = (state: any) => ({   authUser: state.sessionState.authUser }); const authCondition = (authUser: any) => !!authUser; export const Account = compose(   withAuthorization(authCondition),   withRouter,   connect(mapStateToProps) )(AccountComponent); 
 
App Create src/components/App/index.tsx file:
import  * as  React from  "react" ;import  { BrowserRouter, Route, Switch } from  "react-router-dom" ;import  * as  routes from  "../../constants/routes" ;import  { firebase } from  "../../firebase" ;import  { Account } from  "../Account" ;import  { Home } from  "../Home" ;import  { Landing } from  "../Landing" ;import  { Navigation } from  "../Navigation" ;import  { PasswordForget } from  "../PasswordForget" ;import  { withAuthentication } from  "../Session/withAuthentication" ;import  { SignIn } from  "../SignIn" ;import  { SignUp } from  "../SignUp" ;class  AppComponent extends  React.Component {  constructor (props: any  ) {     super (props);     this .state = {       authUser: null      };   }   public  componentDidMount() {     firebase.auth.onAuthStateChanged(authUser  =>  {       authUser         ? this .setState(()  =>  ({ authUser }))         : this .setState(()  =>  ({ authUser: null  }));     });   }   public  render() {     return  (                
                                              true  } path={routes.LANDING} component={Landing} />            true  } path={routes.SIGN_UP} component={SignUp} />            true  } path={routes.SIGN_IN} component={SignIn} />                          exact={true }               path={routes.PASSWORD_FORGET}               component={PasswordForget}             />             true  } path={routes.HOME} component={Home} />             true  } path={routes.ACCOUNT} component={Account} />          </Switch>          div>       </BrowserRouter>      );   } } export const App = withAuthentication(AppComponent); 
 
Home Create src/components/Home/index.tsx file:
import  * as  React from  "react" ;import  { connect } from  "react-redux" ;import  { compose } from  "recompose" ;import  { withRouter } from  'react-router-dom' import  { db } from  "../../firebase" ;import  { withAuthorization } from  "../Session/withAuthorization" ;import  { UserList } from  "./UserList" ;class  HomeComponent extends  React.Component {  public  componentDidMount() {     const  { onSetUsers }: any  = this .props;     db.onceGetUsers().then(snapshot  =>  onSetUsers(snapshot.val()));   }   public  render() {     const  { users }: any  = this .props;     return  (       
         Home</h1>           The Home Page is accessible by every signed in user.p>
         {!!users && }        </div>      );   } } const mapStateToProps = (state: any) => ({   users: state.userState.users }); const mapDispatchToProps = (dispatch: any) => ({   onSetUsers: (users: any) => dispatch({ type: "USERS_SET", users }) }); const authCondition = (authUser: any) => !!authUser; export const Home = compose(   withAuthorization(authCondition),   withRouter,   connect(     mapStateToProps,     mapDispatchToProps   ) )(HomeComponent); 
 
Create src/components/Home/UserList.tsx file:
import  * as  React from  "react" ;interface  InterfaceProps {  users?: any ; } export  class  UserList extends  React.Component {   constructor (props: any  ) {     super (props);   }   public  render() {     const  { users }: any  = this .props;     return  (       
         List of Usernames of Users</h2>           (Saved on Sign Up in Firebase Database)p>
                    {Object .keys(users).map(key  =>  {             return  {users[key].username}</li>;             })}         l>       </div>      );   } } 
 
Landing Create src/components/Landing/index.tsx file:
import  * as  React from  "react" ;export  const  Landing = ()  =>  {  return  (     
       Landing Page</h2>       div>   ); }; 
 
Navigation Create src/components/Navigation/index.tsx file:
import  * as  React from  "react" ;import  { connect } from  "react-redux" ;import  { Link } from  "react-router-dom" ;import  * as  routes from  "../../constants/routes" ;import  { SignOutButton } from  "../SignOut" ;const  NavigationComponent = ({ authUser }: any  ) =>  (  {authUser ?  : }</div>   
 ); const NavigationAuth = () => (                LandingLink>     </li>              HomeLink>     </li>              AccountLink>     </li>             >      </li>    l> ); const  NavigationNonAuth = ()  =>  (               Landing</Link>      li>             Sign In</Link>      li>   </ul>  ); const mapStateToProps = (state: any) => ({   authUser: state.sessionState.authUser }); export const Home = compose(   withRouter,   connect(mapStateToProps) )(NavigationComponent); 
 
PasswordChange Create src/components/PasswordChange/index.tsx file:
import  * as  React from  "react" ;import  { auth } from  "../../firebase" ;interface  InterfaceProps {  error?: any ;   history?: any ;   passwordOne?: string ;   passwordTwo?: string ; } interface  InterfaceState {  error?: any ;   passwordOne?: string ;   passwordTwo?: string ; } export  class  PasswordChangeForm extends  React.Component<  InterfaceProps,   InterfaceState > {   private  static  INITIAL_STATE = {     error: null ,     passwordOne: "" ,     passwordTwo: ""    };   private  static  propKey(propertyName: string , value: string ): object {     return  { [propertyName]: value };   }   constructor (props: any  ) {     super (props);     this .state = { ...PasswordChangeForm.INITIAL_STATE };   }   public  onSubmit = (event: any  ) =>  {     const  { passwordOne }: any  = this .state;     auth       .doPasswordUpdate(passwordOne)       .then(()  =>  {         this .setState(()  =>  ({ ...PasswordChangeForm.INITIAL_STATE }));       })       .catch(error  =>  {         this .setState(PasswordChangeForm.propKey("error" , error));       });     event.preventDefault();   };   public  render() {     const  { passwordOne, passwordTwo, error }: any  = this .state;     const  isInvalid = passwordOne !== passwordTwo || passwordOne === "" ;     return  (         this .onSubmit(event)}>                  value={passwordOne}           onChange={event  =>  this .setStateWithEvent(event, "passwordOne" )}           type ="password"            placeholder="New Password"          />                   value={passwordTwo}           onChange={event  =>  this .setStateWithEvent(event, "passwordTwo" )}           type ="password"            placeholder="Confirm New Password"          />         type  ="submit" >           Reset My Password         </button>          {error && {error.message}p>}
       </form>      );   }   private setStateWithEvent(event: any, columnType: string): void {     this.setState(       PasswordChangeForm.propKey(columnType, (event.target as any).value)     );   } }  
 
PasswordForget Create src/components/PasswordForget/index.tsx file:
import  * as  React from  "react" ;import  { Link } from  "react-router-dom" ;import  { PasswordForgetForm } from  "./PasswordForgetForm" ;import  * as  routes from  "../../constants/routes" export  const  PasswordForget = ()  =>  (  
     PasswordForget</h1>       >    </div>  ); export const PasswordForgetLink = () => (   
      Forgot PasswordLink>   </p>  ); 
 
Create src/components/PasswordForget/PasswordForgetForm.tsx file:
 
🏈 Session Create src/components/Session/withAuthentication.tsx file:
import  * as  React from  "react" ;import  { connect } from  "react-redux" ;import  { firebase } from  "../../firebase" ;interface  InterfaceProps {  authUser?: any ; } interface  InterfaceState {  authUser?: any ; } export  const  withAuthentication = (Component: any  ) =>  {  class  WithAuthentication extends  React.Component<     InterfaceProps,     InterfaceState   > {     public  componentDidMount() {       const  { onSetAuthUser }: any  = this .props;       firebase.auth.onAuthStateChanged(authUser  =>  {         authUser ? onSetAuthUser(authUser) : onSetAuthUser(null );       });     }     public  render() {       return  ;      }   }   const  mapDispatchToProps = (dispatch: any  ) =>  ({     onSetAuthUser: (authUser: any  ) =>        dispatch({ type : "AUTH_USER_SET" , authUser })   });   return  connect(     null ,     mapDispatchToProps   )(WithAuthentication); }; 
 
Create src/components/Session/withAuthorization.tsx file:
import  * as  React from  "react" ;import  { connect } from  "react-redux" ;import  { withRouter } from  "react-router-dom" ;import  { compose } from  "recompose" ;import  * as  routes from  "../../constants/routes" ;import  { firebase } from  "../../firebase" ;interface  InterfaceProps {  history?: any ;   authUser?: any ; } export  const  withAuthorization = (condition: any  ) =>  (Component: any ) => {  class  WithAuthorization extends  React.Componentany  > {    public  componentDidMount() {       firebase.auth.onAuthStateChanged(authUser  =>  {         if  (!condition(authUser)) {           this .props.history.push(routes.SIGN_IN);         }       });     }     public  render() {       return  this .props.authUser ?  : null ;      }   }   const  mapStateToProps = (state: any  ) =>  ({     authUser: state.sessionState.authUser   });   return  compose(     withRouter,     connect(mapStateToProps)   )(WithAuthorization); }; 
 
SignIn Create src/components/SignIn/index.tsx:
import  * as  React from  "react" ;import  { withRouter } from  "react-router-dom" ;import  { PasswordForgetLink } from  "../PasswordForget" ;import  { SignUpLink } from  "../SignUp" ;import  { SignInForm } from  "./SignInForm" ;const  SignInComponent = ({ history }: { [key: string ]: any  } ) =>  (  
     SignIn</h1>       >              </div>  ); export const SignIn = withRouter(SignInComponent); 
 
Create src/components/SignIn/SignInForm.tsx file:
import  * as  React from  "react" ;import  * as  routes from  "../../constants/routes" ;import  { auth } from  "../../firebase" ;interface  InterfaceProps {  email?: string ;   error?: any ;   history?: any ;   password?: string ; } interface  InterfaceState {  email: string ;   error: any ;   password: string ; } export  class  SignInForm extends  React.Component<  InterfaceProps,   InterfaceState > {   private  static  INITIAL_STATE = {     email: "" ,     error: null ,     password: ""    };   private  static  propKey(propertyName: string , value: any ): object {     return  { [propertyName]: value };   }   constructor (props: InterfaceProps ) {     super (props);     this .state = { ...SignInForm.INITIAL_STATE };   }   public  onSubmit = (event: any  ) =>  {     const  { email, password } = this .state;     const  { history } = this .props;     auth       .doSignInWithEmailAndPassword(email, password)       .then(()  =>  {         this .setState(()  =>  ({ ...SignInForm.INITIAL_STATE }));         history.push(routes.HOME);       })       .catch(error  =>  {         this .setState(SignInForm.propKey("error" , error));       });     event.preventDefault();   };   public  render() {     const  { email, password, error } = this .state;     const  isInvalid = password === ""  || email === "" ;     return  (         this .onSubmit(event)}>                  value={email}           onChange={event  =>  this .setStateWithEvent(event, "email" )}           type ="text"            placeholder="Email Address"          />                   value={password}           onChange={event  =>  this .setStateWithEvent(event, "password" )}           type ="password"            placeholder="Password"          />         type  ="submit" >           Sign In         </button>          {error && {error.message}p>}
       </form>      );   }   private setStateWithEvent(event: any, columnType: string): void {     this.setState(SignInForm.propKey(columnType, (event.target as any).value));   } }  
 
SignOut Create src/components/SignOut/index.tsx file:
import  * as  React from  "react" ;import  { auth } from  "../../firebase" ;export  const  SignOutButton = ()  =>  (  type  ="button"  onClick={auth.doSignOut}>    Sign Out   </button>  ); 
 
SignUp Create src/components/SignUp/index.tsx file:
import  * as  React from  "react" ;import  { auth } from  "../../firebase" ;export  const  SignOutButton = ()  =>  (  type  ="button"  onClick={auth.doSignOut}>    Sign Out   </button>  ); 
 
Create SingUpForm.tsx file:
import  * as  React from  "react" ;import  * as  routes from  "../../constants/routes" ;import  { auth, db } from  "../../firebase" ;interface  InterfaceProps {  email?: string ;   error?: any ;   history?: any ;   passwordOne?: string ;   passwordTwo?: string ;   username?: string ; } interface  InterfaceState {  email: string ;   error: any ;   passwordOne: string ;   passwordTwo: string ;   username: string ; } export  class  SignUpForm extends  React.Component<  InterfaceProps,   InterfaceState > {   private  static  INITIAL_STATE = {     email: "" ,     error: null ,     passwordOne: "" ,     passwordTwo: "" ,     username: ""    };   private  static  propKey(propertyName: string , value: any ): object {     return  { [propertyName]: value };   }   constructor (props: InterfaceProps ) {     super (props);     this .state = { ...SignUpForm.INITIAL_STATE };   }   public  onSubmit(event: any ) {     event.preventDefault();     const  { email, passwordOne, username } = this .state;     const  { history } = this .props;     auth       .doCreateUserWithEmailAndPassword(email, passwordOne)       .then((authUser: any  ) =>  {                  db.doCreateUser(authUser.user.uid, username, email)           .then(()  =>  {             this .setState(()  =>  ({ ...SignUpForm.INITIAL_STATE }));             history.push(routes.HOME);           })           .catch(error  =>  {             this .setState(SignUpForm.propKey("error" , error));           });       })       .catch(error  =>  {         this .setState(SignUpForm.propKey("error" , error));       });   }   public  render() {     const  { username, email, passwordOne, passwordTwo, error } = this .state;     const  isInvalid =       passwordOne !== passwordTwo ||       passwordOne === ""  ||       email === ""  ||       username === "" ;     return  (         this .onSubmit(event)}>                  value={username}           onChange={event  =>  this .setStateWithEvent(event, "username" )}           type ="text"            placeholder="Full Name"          />                   value={email}           onChange={event  =>  this .setStateWithEvent(event, "email" )}           type ="text"            placeholder="Email Address"          />                   value={passwordOne}           onChange={event  =>  this .setStateWithEvent(event, "passwordOne" )}           type ="password"            placeholder="Password"          />                   value={passwordTwo}           onChange={event  =>  this .setStateWithEvent(event, "passwordTwo" )}           type ="password"            placeholder="Confirm Password"          />         type  ="submit" >           Sign Up         </button>          {error && {error.message}p>}
       </form>      );   }   private setStateWithEvent(event: any, columnType: string) {     this.setState(SignUpForm.propKey(columnType, (event.target as any).value));   } }    
 
After then, please confirm http://localhost:3000 again. You can see some pages for sign up, sign in, password reset, change password and sign out.
🐮 firebase auth Create src/firebase/auth.tsx file:
import  { auth } from  "./firebase" ;export  const  doCreateUserWithEmailAndPassword = (  email: string ,   password: string  ) => auth.createUserWithEmailAndPassword(email, password); export  const  doSignInWithEmailAndPassword = (email: string , password: string  ) =>   auth.signInWithEmailAndPassword(email, password); export  const  doSignOut = ()  =>  auth.signOut();export  const  doPasswordReset = (email: string  ) =>   auth.sendPasswordResetEmail(email); export  const  doPasswordUpdate = async  (password: string ) => {  if  (auth.currentUser) {     await  auth.currentUser.updatePassword(password);   }   throw  Error ("No auth.currentUser!" ); }; 
 
db Create src/firebase/db.ts file:
import  { db } from  "./firebase" ;export  const  doCreateUser = (id: string , username: string , email: string  ) =>   db.ref(`users/${id} ` ).set({     email,     username   }); export  const  onceGetUsers = ()  =>  db.ref("users" ).once("value" );
 
firebase Create src/firebase/firebase.ts file:
import  * as  firebase from  "firebase/app" ;import  "firebase/auth" ;import  "firebase/database" ;const  config = {  apiKey: "YOUR_API_KEY" ,   authDomain: "YOUR_AUTH_DOMAIN" ,   databaseURL: "YOUR_DATABASE_URL" ,   messagingSenderId: "YOUR_MESSAGING_SENDER_ID" ,   projectId: "YOUR PROJECT_ID" ,   storageBucket: "YOUR_STORAGE_BUCKET"  }; if  (!firebase.apps.length) {  firebase.initializeApp(config); } export  const  auth = firebase.auth();export  const  db = firebase.database();
 
index Create src/firebase/index.ts file:
import  * as  auth from  "./auth" ;import  * as  db from  "./db" ;import  * as  firebase from  "./firebase" ;export  { auth, db, firebase };
 
 🎉 reducers index Create src/reducers/index.ts file:
import  { combineReducers } from  "redux" ;import  { sessionReducer } from  "./session" ;import  { userReducer } from  "./user" ;export  const  rootReducer = combineReducers({  sessionState: sessionReducer,   userState: userReducer }); 
 
session Create src/reducers/session.ts file:
const  INITIAL_STATE = {  authUser: null  }; const  applySetAuthUser = (state: any , action: any  ) =>  ({  ...state,   authUser: action.authUser }); export  function  sessionReducer (state = INITIAL_STATE, action: any  )  {  switch  (action.type) {     case  "AUTH_USER_SET" : {       return  applySetAuthUser(state, action);     }     default :       return  state;   } } 
 
user Create src/reducers/user.ts file:
const  INITIAL_STATE = {  users: {} }; const  applySetUsers = (state: any , action: any  ) =>  ({  ...state,   users: action.users }); export  function  userReducer (state = INITIAL_STATE, action: any  )  {  switch  (action.type) {     case  "USERS_SET" : {       return  applySetUsers(state, action);     }     default :       return  state;   } } 
 
 🏀 store Create src/store/index.ts file:
import  { createStore } from  "redux" ;import  { rootReducer } from  "../reducers" ;const  store = createStore(rootReducer);export  default  store;
 
🐠 GitHub Repository Whole files of this tutorial are as follows:
https://github.com/morizyun/react-redux-typescript-firebase-auth 
 🐰 References 
    
    
    
     
    
    
    🖥 Recommended VPS Service 
    
    VULTR   provides high performance cloud compute environment for you.
    Vultr has 15 data-centers strategically placed around the globe, you can use a VPS with 512 MB memory for just $ 2.5 / month ($ 0.004 / hour).
    In addition, Vultr is up to 4 times faster than the competition, so please check it => Check Benchmark Results  !!