javascript - React Native + Redux basic authentication -


i'm looking way create basic authentication react-native app. couldn't find example react-native app.

  • to login, app sends email/password + clientsecret server
  • if ok, server returns accesstoken + refreshtoken
  • the user logged in, other requests include bearer accesstoken.
  • if accesstoken expires, app requests new 1 refreshtoken automatically.
  • the user stays logged in time, states should saved in phone.

what best approach this?

thanks.

when app communicates http api enforces form of authentication, app typically follows these steps:

  1. the app not authenticated, prompt user log in.
  2. the user enters credentials (username , password), , taps submit.
  3. we send these credentials api, , inspect response:
    • on success (200 - ok): cache authentication token/ hash, because we're going use token/ hash in every subsequent request.
      • if token/ hash not work during of subsequent api requests (401 - unauthorized), we'll need invalidate hash/ token , prompt user log in again.
    • or, on failure (401 - unauthorized): display error message user, prompting them re-enter credentials.

logging in

based on work flow defined above our app starts displaying login form, step 2 kicks in when user taps login button dispatches login action creator below:

/// actions/user.js  export function login(username, password) {   return (dispatch) => {      // use update store state of `isloggingin`               // can used display activity indicator on login     // view.     dispatch(loginrequest())      // note: base64 encode method works in nodejs, use     // implementation works platform:     // `base64-js` react native,     // `btoa()` browsers, etc...     const hash = new buffer(`${username}:${password}`).tostring('base64')     return fetch('https://httpbin.org/basic-auth/admin/secret', {       headers: {         'authorization': `basic ${hash}`       }     })     .then(response => response.json().then(json => ({ json, response })))     .then(({json, response}) => {       if (response.ok === false) {         return promise.reject(json)       }       return json     })     .then(       data => {         // data = { authenticated: true, user: 'admin' }         // pass `authentication hash` down reducer         // can used in subsequent api requests.          dispatch(loginsuccess(hash, data.user))       },       (data) => dispatch(loginfailure(data.error || 'log in failed'))     )   } } 

there's lot of code in function above, take comfort in fact majority of code sanitising response , can abstracted away.

the first thing dispatch action login_request updates our store , lets know user isloggingin.

dispatch(loginrequest()) 

we use display activity indicator (spinning wheel, "loading...", etc.), , disable log in button in our log in view.

next base64 encode user's username , password http basic auth, , pass request's headers.

const hash = new buffer(`${username}:${password}`).tostring('base64') return fetch('https://httpbin.org/basic-auth/admin/secret', {   headers: {     'authorization': `basic ${hash}`   } /* ... */ 

if went well, we'll dispatch login_success action, results in having authentication hash in our store, we'll use in subsequent requests.

dispatch(loginsuccess(hash, data.user)) 

on flip side, if went wrong want let user know:

dispatch(loginfailure(data.error || 'log in failed') 

the loginsuccess, loginfailure, , loginrequest action creators generic , don't warrant code samples. see: https://github.com/peterp/redux-http-basic-auth-example/blob/master/actions/user.js)

reducer

our reducer typical:

/// reducers/user.js function user(state = {   isloggingin: false,   isauthenticated: false }, action) {   switch(action.type) {     case login_request:       return {         isloggingin: true, // show loading indicator.         isauthenticated: false       }     case login_failure:       return {         isloggingin: false,         isauthenticated: false,         error: action.error       }     case login_success:       return {         isloggingin: false,         isauthenticated: true, // dismiss login view.         hash: action.hash, // used in subsequent api requests.         user: action.user       }     default:       return state   } } 

subsequent api requests

now have authentication hash in our store can pass subsequent request's headers.

in our example below we're fetching list of friends our authenticated user:

/// actions/friends.js export function fetchfriends() {   return (dispatch, getstate) => {      dispatch(friendsrequest())      // notice how grab hash store:     const hash = getstate().user.hash     return fetch(`https://httpbin.org/get/friends/`, {       headers: {         'authorization': `basic ${hash}`       }     })     .then(response => response.json().then(json => ({ json, response })))     .then(({json, response}) => {       if (response.ok === false) {         return promise.reject({response, json})       }       return json     })     .then(       data => {         // data = { friends: [ {}, {}, ... ] }         dispatch(friendssuccess(data.friends))       },       ({response, data}) => {         dispatch(friendsfailure(data.error))          // did our request fail because our auth credentials aren't working?         if (response.status == 401) {           dispatch(loginfailure(data.error))         }       }     )   } } 

you may find api requests typically dispatch same 3 actions above: api_request, api_success, , api_failure, , such majority of request/ response code can pushed redux middleware.

we fetch hash authentication token store , setup request.

const hash = getstate().user.hash return fetch(`https://httpbin.org/get/friends/`, {   headers: {     'authorization': `basic ${hash}`   } }) /* ... */ 

if api response 401 status code we've got remove our hash store, , present user log in view again.

if (response.status == 401) {   dispatch(loginfailure(data.error)) } 

i've answered question generically , dealing http-basic-auth.

i think concept may remain same, you'll push accesstoken , refreshtoken in store, , extract in subsequent requests.

if request fails you'll have dispatch action updates accesstoken, , recalls original request.


Comments

Popular posts from this blog

gridview - Yii2 DataPorivider $totalSum for a column -

java - Suppress Jboss version details from HTTP error response -

Sass watch command compiles .scss files before full sftp upload -