Je cherche un moyen de créer une authentification de base pour mon application react-native . Je ne trouvais pas de bon exemple pour cette application.
Quelle serait la meilleure approche pour cela?
Merci.
Lorsqu'une application communique avec une API HTTP qui applique une forme d'authentification, l'application suit généralement les étapes suivantes:
En fonction du flux de travail défini ci-dessus, notre application commence par afficher un formulaire de connexion. Step 2 démarre lorsque l'utilisateur appuie sur le bouton de connexion qui envoie le créateur de l'action login
ci-dessous:
/// actions/user.js
export function login(username, password) {
return (dispatch) => {
// We use this to update the store state of `isLoggingIn`
// which can be used to display an activity indicator on the login
// view.
dispatch(loginRequest())
// Note: This base64 encode method only works in NodeJS, so use an
// implementation that works for your platform:
// `base64-js` for React Native,
// `btoa()` for 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' }
// We pass the `authentication hash` down to the reducer so that it
// can be used in subsequent API requests.
dispatch(loginSuccess(hash, data.user))
},
(data) => dispatch(loginFailure(data.error || 'Log in failed'))
)
}
}
La fonction ci-dessus contient beaucoup de code, mais rassurez-vous sur le fait que La majorité du code nettoie la réponse et peut être extraite.
La première chose que nous faisons est d’envoyer une action LOGIN_REQUEST
qui met à jour notre magasin et nous informe que l’utilisateur isLoggingIn
.
dispatch(loginRequest())
Nous l'utilisons pour afficher un indicateur d'activité (rouet, "Chargement ...", etc.) et pour désactiver le bouton de connexion dans notre vue de connexion.
Ensuite, nous encodons en base64 le nom d'utilisateur et le mot de passe de l'utilisateur pour l'authentification de base http, et nous le transmettons aux en-têtes de la requête.
const hash = new Buffer(`${username}:${password}`).toString('base64')
return fetch('https://httpbin.org/basic-auth/admin/secret', {
headers: {
'Authorization': `Basic ${hash}`
}
/* ... */
Si tout se passe bien, nous enverrons une action LOGIN_SUCCESS
, ce qui nous permettra d'avoir une authentification hash
dans notre magasin, que nous utiliserons dans les requêtes suivantes.
dispatch(loginSuccess(hash, data.user))
D'un autre côté, si quelque chose ne va pas, nous voulons également informer l'utilisateur:
dispatch(loginFailure(data.error || 'Log in failed')
Les créateurs d'action loginSuccess
, loginFailure
et loginRequest
sont assez génériques et ne justifient pas vraiment des exemples de code. Voir: https://github.com/peterp/redux-http-basic-auth-example/blob/master/actions/user.js)
Notre réducteur est aussi typique:
/// reducers/user.js
function user(state = {
isLoggingIn: false,
isAuthenticated: false
}, action) {
switch(action.type) {
case LOGIN_REQUEST:
return {
isLoggingIn: true, // Show a loading indicator.
isAuthenticated: false
}
case LOGIN_FAILURE:
return {
isLoggingIn: false,
isAuthenticated: false,
error: action.error
}
case LOGIN_SUCCESS:
return {
isLoggingIn: false,
isAuthenticated: true, // Dismiss the login view.
hash: action.hash, // Used in subsequent API requests.
user: action.user
}
default:
return state
}
}
Maintenant que nous avons un hachage d’authentification dans notre magasin, nous pouvons le transférer dans les en-têtes des requêtes suivantes.
Dans notre exemple ci-dessous, nous recherchons une liste d'amis pour notre utilisateur authentifié:
/// actions/friends.js
export function fetchFriends() {
return (dispatch, getState) => {
dispatch(friendsRequest())
// Notice how we grab the hash from the 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))
}
}
)
}
}
Vous constaterez peut-être que la plupart des demandes d'API distribuent généralement les mêmes 3 actions que ci-dessus: API_REQUEST
, API_SUCCESS
et API_FAILURE
et qu'en tant que telles, le code de requête/réponse peut être transmis au middleware Redux.
Nous récupérons le jeton d'authentification par hachage dans le magasin et configurons la demande.
const hash = getState().user.hash
return fetch(`https://httpbin.org/get/friends/`, {
headers: {
'Authorization': `Basic ${hash}`
}
})
/* ... */
Si la réponse de l'API avec un code d'état 401, nous devons alors supprimer notre hachage du magasin et redonner à l'utilisateur une nouvelle vue de connexion.
if (response.status == 401) {
dispatch(loginFailure(data.error))
}
J'ai répondu à la question de manière générique et ne traite que de http-basic-auth.
Je pense que le concept peut rester le même, vous allez pousser le accessToken
et le refreshToken
dans le magasin et l'extraire dans les requêtes suivantes.
Si la demande échoue, vous devrez envoyer une autre action mettant à jour le accessToken, puis rappelant la demande initiale.
Je n'ai pas vu beaucoup d'exemples dans ce domaine et je pense que c'est certainement quelque chose qui nécessite une plus grande couverture. Je n'ai pas encore implémenté auth moi-même, sinon je vous indiquerais des exemples de code. Mais je peux vous indiquer quelques liens que j'ai rassemblés qui pourraient vous aider dans la bonne direction ...
Quelle que soit la manière dont vous effectuez votre autorisation, vous devez stocker de manière sécurisée vos jetons d'accès, d'actualisation et de secret. Sur iOS, je pense que vous utiliseriez keychain et pour Android, cela ressemble à KeyStore est le chemin. Vous pouvez trouver oblador/react-native-keychain utile, même s’il ne prend pas encore en charge Android it et qu’il pourrait bientôt prendre en charge Android .
Je travaille actuellement sur une série de didacticiels vidéo qui répond au moins à certaines des questions que vous posez. La vidéo avec une transcription et un exemple de code est disponible à l'adresse suivante: http://codecookbook.co/post/how-to-build-a-react-native-login-form-with-redux-pt1/