React-native : how to check if it's the user's first connection? - react-native

I 'm new to react-native and I would like to set up my first page of the app with
1- The user never logged in the app, I 'll present the app with some slides + go to signup page
2 -The user is already in => directly go to the user page
3 -The user is already in but the id is not correct
Can you guide me through it ?
For the first point I really don't know how to check if the user exist in my db
For the second and third points I thought I'd try :
onPressLogin(){
fetch('linktomyAPI',{
method: 'POST',
headers:{
'Content-Type' : 'application/json',
'Accept':'application/json'
},
body: JSON.stringify({
username:this.state.username,
password: this.state.password,
})
})
.then(response => response.json())
.then((responseData) =>{
if(responseData.error !== 1){ // verify the success case, as you didn't provide the success case i am using the error code
this.setState({ // its recommended you verify the json before setting it to state.
userdetail: responseData,
})
setTimeout(() => {
Actions.Authentication();
}, 2300);
AsyncStorage.setItem('username', this.state.username); // its setItem not saveitem.
} else {
console.log(responseData);
Alert.alert(JSON.stringify(responseData)); // Alerts doesn't allow arrays or JSONs, so stringify them to view in Alerts
}
}).catch((error) => {
// handle catch
console.log("error:"+JSON.stringify(error));
});
}
Do you think I can do this way, is that relevant?
Thanks for taking the time to answer me. I'm really new so I need help and explanations. Thanks !!! :)

you can use the UserInfo to do. firstly, you have saved the user info in memory use Session js and in the device local file use AsyncStore. you already do it use the AsyncStore.
firstly save the user info into Session,the Session structure is:{id:"dd333",name:"john"},
...
setTimeout(() => {
Actions.Authentication();
}, 2300);
Session.id = res.id;
Session.name = res.name;
AsyncStorage.setItem('userinfo', Json.stringfy(res));
then you can show diffent page and condition.
// in the component which you want compoentDidMount
componentDidMount() {
// here you can try to get it from AsyncStore if the Session is null.
// then hanle it as the followng
if(Session.id == ""){
//default it is "", it means the user does not login
} else if(Session.id != "222"){
// the user id is not correct
} else {
// here is the user login and id is correct
}
}

Related

Web app that runs in Microsoft Teams (personal tab) doesn't always work on Desktop version

I have a Web app built in Vuejs and has SSO authentification using microsoftTeams.authentication.getAuthToken when running in Teams, or microsoftAuthLib when running in the browser.
Inside the company's network or when connected to the VPN everything works absolutely fine.
We recently opened it outside of the VPN and we created a public certificate for it. So when I disconnect the VPN, it works:
In any browser (outside of Teams).
Teams browser version.
Teams on Android/iPhone.
But it doesn't work on Teams Windows Desktop version, it fails with the following error:
Refused to display
'https://login.microsoftonline.com/.../oauth2/authorize?...' in a
frame because it set 'X-Frame-Options' to 'deny'.
Anybody has an idea what could be the issue? And why would it work on the company's VPN but not outside?And only on specific cases? I am lost, any help would be appreciated.
Thank you
*** EDIT / ADDED SSO REDIRECT CODE ***
import * as microsoftTeams from "#microsoft/teams-js";
import * as microsoftAuthLib from "msal";
import settings from './settings.js';
var msalConfig = {
auth: {
clientId: settings.sso.id,
authority: settings.sso.authority
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: true
}
};
var requestObj = {
scopes: settings.sso.scopes
};
var myMSALObj = new microsoftAuthLib.UserAgentApplication(msalConfig);
myMSALObj.handleRedirectCallback(authRedirectCallBack);
function authRedirectCallBack(error, response) {
if (error) {
console.log(error);
} else {
console.log("token type is:" + response.tokenType);
}
}
function loginRedirect(requestObj) {
let account = myMSALObj.getAccount();
if (!account) {
myMSALObj.loginRedirect(requestObj);
return false;
} else {
return true;
}
}
function acquireMsalToken() {
return new Promise(function (resolve) {
resolve(myMSALObj.acquireTokenSilent(requestObj).then(token => {
return token.accessToken;
}).catch(error => {
acquireMsalTokenRedirect(error);
}));
})
}
function acquireTeamsToken() {
return new Promise((resolve, reject) => {
microsoftTeams.authentication.getAuthToken({
successCallback: (result) => {
resolve(result);
},
failureCallback: (error) => {
reject(error);
}
});
});
}
function acquireMsalTokenRedirect(error) {
if (error.errorCode === "consent_required" ||
error.errorCode === "interaction_required" ||
error.errorCode === "login_required") {
myMSALObj.acquireTokenRedirect(requestObj);
}
}
var msal = {
autoSignIn: function () {
return loginRedirect(requestObj);
},
acquireToken: async function () {
if (settings.sso.inTeams) {
microsoftTeams.initialize();
microsoftTeams.enterFullscreen();
return acquireTeamsToken();
} else {
let signedIn = msal.autoSignIn();
if (signedIn) {
return acquireMsalToken();
}
}
}
}
export default msal
This error means that you are trying to redirect your tab's iframe to the AAD login flow which in turn is unable to silently generate an auth token for you and is attempting to show an interactive flow (e.g. sign in or consent):
Refused to display
'https://login.microsoftonline.com/.../oauth2/authorize?...' in a
frame because it set 'X-Frame-Options' to 'deny'.
To avoid this issue you need to try and acquire a token silently and if that fails use the microsoftTeams.authentication.authenticate API to open a popup window and conduct the AAD login flow there.
Replacing the acquireTeamsToken() function with the following resolved the issue.
function acquireTeamsToken() {
return new Promise((resolve, reject) => {
microsoftTeams.initialize(() => {
microsoftTeams.authentication.authenticate({
url: window.location.origin + "/ms-teams/auth-start",
width: 600,
height: 535,
successCallback: (result) => {
resolve(result);
},
failureCallback: (error) => {
reject(error);
}
});
});
});
}
I found this documentation very helpful on how to create the Authentication pop up and how to create a Callback window with the Token in it.
You might also want to cache the token and only create a popup when it expires.
This might be because you're using the auth popup option instead of the redirect option in whichever auth library you're using (hopefully MSAL 2.0). Teams is a little different because it's actually launching a popup for you when necessary, so although it sounds a bit strange, you actually want to use the redirect option, inside the popup that is launched. What might help is to look at the new SSO Sample app in the Teams PnP samples.
Go to: %APPDATA%\Microsoft\Teams
Open the file hooks.json (if it's not there, create it)
Add the following to it: {"enableSso": false, "enableSsoMac": false}
That's it, now Teams desktop has the same authentication workflow as the browser version. Have a nice day.

ASync/Await is not working as expected in router.BeforeEach guard in vue?

this is my router guard :
router.beforeEach(async (to,from,next)=>{
await store.dispatch('GetPermission');
if(to.matched.some(record => record.meta.requireAuth)){
let permissions=store.state.permissions; //getting empty
console.log(permissions);
if(permissions.filter(per => (per.name === 'read_list').length!=0)){
next({
path:'/dashboard/create'
})
}
else{
next()
}
}
// else if(to.matched.some(record => record.meta.requireAuth)){
// if(store.token!=null){
// next({
// path:'/dashboard'
// })
// }
// else{
// next()
// }
// }
else{
next()
}
});
problem is here though i m using await in dispatch method , i m not getting state value of permissions which is initially empty
here is vuex store code :
GetPermission(context){
axios.defaults.headers.common['Authorization']='Bearer ' + context.state.token
axios.get('http://127.0.0.1:8000/api/user').then((response)=>{
console.log(response)
context.commit('Permissions',response.data.permission)
})
//mutation:
Permissions(state,payload){
state.permissions=payload
}
//state
state:{
error:'',
token:localStorage.getItem('token') || null,
permissions:'',
success:'',
isLoggedin:'',
LoggedUser:{}
}
help me to solve it please ??
actions in Vuex are asynchronous. The only way to let the calling function (initiator of action) to know that an action is complete - is by returning a Promise and resolving it later.
Here is an example: myAction returns a Promise, makes a http call and resolves or rejects the Promise later - all asynchronously
actions: {
myAction(context, data) {
return new Promise((resolve, reject) => {
// Do something here... lets say, a http call using vue-resource
this.$http("/api/something").then(response => {
// http success, call the mutator and change something in state
resolve(response); // Let the calling function know that http is done. You may send some data back
}, error => {
// http failed, let the calling function know that action did not work out
reject(error);
})
})
}
}
Now, when your Vue component initiates myAction, it will get this Promise object and can know whether it succeeded or not. Here is some sample code for the Vue component:
export default {
mounted: function() {
// This component just got created. Lets fetch some data here using an action
this.$store.dispatch("myAction").then(response => {
console.log("Got some data, now lets show something in this component")
}, error => {
console.error("Got nothing from server. Prompt user to check internet connection and try again")
})
}
}
Also,you are calling same route when no permission match, in that case it always call your same route and make infinite loop.
Redirect to access denied page if permission denied.

Where and how to get `identityId` using AWS Amplify?

So I'm trying to follow along the guide in the docs and I'm stuck here
Storage.get('test.txt', {
level: 'protected',
identityId: 'xxxxxxx' // the identityId of that user
})
.then(result => console.log(result))
.catch(err => console.log(err));
How does one get that identityId?
I found a hack to this from Auth.currentUserCredentials() by saving the identityId to a custom attribute on successful user login:
const CUSTOM_IDENTITY_FIELD = "custom:identityId";
if (attributes && !attributes[CUSTOM_IDENTITY_FIELD]) {
await Auth.updateUserAttributes(currUser, {
[CUSTOM_IDENTITY_FIELD]: (await Auth.currentUserCredentials())
.identityId,
});
onInfo("Welcome to Tippify, " + currUser.username);
}
With this, I could also implement a Firebase first-time log in functionality.
Later when I wanted to query the user image from Storage:
Storage.get(user.picture, {
level: "protected",
identityId: user[CUSTOM_IDENTITY_FIELD],
})
.then(setPicture)
.catch(onError);

The sms code has expired. Please re-send the verification code to try again

Whenever I tried to login with phone number using react-native-firebase sdk, I recieve OTP code through sms and when I submit the recieved code, an error is there saying:"The sms code has expired. Please re-send the verification code to try again." And here point to be noted that an entry for respective phone number is writing in Users section of firebase even there is an error.
I am using following:
NodeJS: v8.11.1,
NPM: v5.6.0,
react-native: "^0.59.9",
react-native-firebase: "^5.5.3"
Some links I have already tried are:
1. https://github.com/invertase/react-native-firebase-
docs/blob/master/docs/auth/phone-auth.md
2. https://stackoverflow.com/questions/46522726/firebase-phone-
authentication-error-the-sms-code-has-expired
3. https://www.bountysource.com/issues/45308170-firebase-phone-
number-auth-integration
4. https://medium.com/#chrisbianca/getting-started-with-firebase-
authentication-on-react-native-a1ed3d2d6d91
5. https://invertase.io/oss/react-native-firebase/v6/auth/phone-
auth
In MobileRegistration.js:
navigateToOtpScreen() {
console.log("Phone number: ", "+91" + this.state.phoneNumber)
firebase.auth().signInWithPhoneNumber("+91" +
this.state.phoneNumber)
.then(confirmResult => {
this.setState({ confirmResult, message: 'Code has been sent!'})
this.props.navigation.navigate('EnterOtp', { 'confirmResult':
confirmResult})
})
.catch(error => {
alert(error.message);
this.setState({ message: `Sign In With Phone Number Error:
${error.message}` })
});
};
In EnterOtp.js:
componentDidMount() {
this.unsubscribe = firebase.auth().onAuthStateChanged((user) => {
alert(JSON.stringify(user));
if (user) {
this.setState({
user: user.toJSON()
});
} else {
// User has been signed out, reset the state
this.setState({
user: null,
message: '',
otp: '',
otp1: '',
otp2: '',
otp3: '',
otp4: '',
otp5: '',
otp6: ''
});
}
});
}
componentWillUnmount() {
if (this.unsubscribe) this.unsubscribe();
}
verifyOTP = async () => {
const {
confirmResult,
} = this.props.navigation.state.params;
let otp = this.state.otp + "" + this.state.otp1 + "" + this.state.otp2 + "" + this.state.otp3 + "" + this.state.otp4 + "" + this.state.otp5 + "" + this.state.otp6
if (confirmResult && otp.length) {
alert(otp);
confirmResult.confirm(otp).then((user) => {
AsyncStorage.setItem('accessToken', confirmResult._verificationId);
this.props.navigation.navigate('SetupCoverVideo');
this.setState({
message: 'Code Confirmed!'
});
})
.catch(error => {
alert(error.message) && this.setState({
message: `Code Confirm Error: ${error.message}`
})
});
}
}
Expected Result: Code should be verified and an entry should be in Users section of firebase and navigate to SetupCoverVideo.
Actual Result: Facing an error saying: "The sms code has expired. Please re-send the verification code to try again." And here point to be noted that an entry for respective phone number is writing in Users section of firebase even there is an error.
I am wondering for the solution. Anyone please assist me.
Apparently, some recent versions of Android are smart enough to receive the SMS verification code and use it to authenticate the user. This authentication happens in the background while the user still receives the verification code in an SMS. When the user tries to enter the verification code, he/she gets a message that the verification code expired, because Android has already used it (in the background) and has already logged in the user! To double-check that, check the Firebase Console. You should find that this new user has been added to the list of users.
To avoid receiving the verification code expiry message, we need to set up a listener for "authentication changes." As soon as Android logs in the user in the background, this listener should navigate the user away from the login screen, in which he/she was supposed to enter the verification code. The following demonstrates how this can be implemented. I would add the following code to the login screen.
Example code for use with functional components:
useEffect( () => {
firebase.auth().onAuthStateChanged( (user) => {
if (user) {
// Obviously, you can add more statements here,
// e.g. call an action creator if you use Redux.
// navigate the user away from the login screens:
props.navigation.navigate("PermissionsScreen");
}
else
{
// reset state if you need to
dispatch({ type: "reset_user" });
}
});
}, []);
Example code for use with class components:
// I did NOT test this version, because I use functional components.
componentDidMount() {
firebase.auth().onAuthStateChanged( (user) => {
if (user) {
// Obviously, you can add more statements here,
// e.g. call an action creator if you use Redux.
// navigate the user away from the login screens:
props.navigation.navigate("PermissionsScreen");
}
else
{
// reset state if you need to
this.setState({
user: null,
messageText: '',
codeInput: '',
phoneNo: '',
confirmResult: null,
});
}
});
};
You need to check for background authentication using:
conponentDidMount() {
firebase.auth().onAuthStateChanged((user) => {
if (user) {
// alert(JSON.stringify(user))
// Obviously, you can add more statements here,
// e.g. call an action creator if you use Redux.
// navigate the user away from the login screens:
}
});
}
Then you need to log out your user once you are done with it (I faced this issue of old user session already present while new user was coming to authenticate)
So, at the time of logging out use:
if (firebase.auth().currentUser)
firebase.auth().currentUser.delete();
And you are all set!

How to setGenericPassword in Keychain with React-Native?

using the following code somehow it stops reading the lines and I get stuck without solutions. So I am trying to setGenericPassword using react-native-keychain but the message from console.log that is inside function I can see it and the one after doesn't. So dispatch() is not called ever it goes straight to catch()
Any idea what is going wrong here?
return axios.post(SIGNUP_URL, { email, password }).then((response) => {
var { user_id, token } = response.data;
Keychain.setGenericPassword(user_id, token, console.log('I can see this'));
console.log('I can not see this');
dispatch(authUser(user_id));
}).catch((error) => {
dispatch(addAlert("Could not sign up."));
});