Clear cache when Logout ionic 2 - authentication

i have a case,
i have 2 different account for login, i have profile page,and i can change my name in my profile page, and success, but when i logout and try to login again with different account to see different data in profile page it wasn't Change, it still display data from the previous account, but when I clear it manually the cache, the data it's updated
how to automatically clear cache when user logout ?
this is my logout at auth-data.ts
logoutUser()
{
return this.fireAuth.signOut();
}
logout at home.ts
logoutUser(){
this.authData.logoutUser().then(() => {
this.navCtrl.setRoot(LoginPage);
});
}

Related

Vue,js used with Supabase - can't update signIn button after logging in with Oauth

async handleSignInSignOutButtonClick() {
if (!this.isSignedIn) {
supabase.auth.signIn({ provider: "google" });
this.$store.commit("signIn", supabase.auth.session());
window.location.reload();
return;
}
await this.$store.commit("signOut");
supabase.auth.signOut();
window.location.reload();
},
The above function is triggered by a sign-in button, which is supposed to become a sign-out button and the icon of the user after logging in.
When The function fires, supabase redirects me to Google OAuth consent screen. However, after logging in and redirecting back to my app, the sign-in button stays there until I manually refresh the page.
What is wrong with my code...
There are a couple of things going on that you need to be aware of. For starters you are reloading your page when you don't need to in the handleSignInSignOutButtonClick() function.
When the authentication process begins, your app will be redirected to Google OAuth consent screen as you have discovered. Once the authentication is complete, you will be redirected back to your app and the reload occurs automatically.
The second point is that you can make use of the supabase.auth.onAuthStateChange() event to help you. My suggestion would be to listen for this event when you create your supabase client so it listens for the duration of your app instance. During that event handling, you can assign the user to the store (or anywhere you want to save the user data) based upon the state change. Your app can be reactive to state changes.
In your supabase client setup code:
const supabaseUrl = process.env.SUPABASE_URL // your supabaseUrl
const supabaseAnonKey = process.env.SUPABASE_ANON_KEY // your supabaseKey
const supabase = createClient(supabaseUrl, supabaseAnonKey)
/**
* Set up the authentication state change listener
*
* #param {string} event The event indicates what state changed (SIGN_IN, SIGN_OUT etc)
* #param {object} session The session contains the current user session data or null if there is no user
*/
supabase.auth.onAuthStateChange((event, session) => {
const user = session?.user || null;
// Save your user to your desired location
$store.commit("user", user);
});
Now you have your user data being saved whenever the user logs in and a null being set for the user data when the user logs out. Plus any page refreshes are handled by the change state event listener or any other instance that might change the user state. For example, you could have other login or logout buttons and the single listener would pick them up.
Next is to deal with the actual process of logging in or out. In your component Vue file (from your example):
async handleSignInSignOutButtonClick() {
if ($store.state.user === null) {
await supabase.auth.signIn(
{ provider: "google" },
{ redirectTo: "where_to_go_on_login" }))
} else {
await supabase.auth.signOut()
$router.push("your_logged_out_page")
}
}
Finally for your button change state to indicate logged in or logged out, you can simply observe the store user state.
<button v-if="user">Sign Out</button>
<button v-else>Sign In</button>
This way your button will update whenever the user state changes. The user state changes whenever a user logs in or out, and your code is much more compact and readable.
Once final observation that you may already be doing anyway. I would recommend that you put all of your authentication code into a single file and expose the log in and log out functions for your app use as an export to use in component files. This way everything to do with login and logout is handled in a single location and this code is abstracted away from the component file. If you ever wanted to switch from Supabase you could easily update one or two files and everything else would just keep working.

Reset store after refresh webpage

I have a problem with the user object in nuxt authorization.
await this.$auth.loginWith('local', {
data: this.form
}).then((res) => {
this.$auth.setUser(res.data.user)
return response;
});
When I log in and redirect me to the subpage for the logged in. On the subpage, I display the user data that I received when logging in. The problem is that when I refresh the page, the user object becomes empty but the login status remains. What's the problem? I'm getting the user object with $ auth.user.username etc.

Auto Sign In with Cognito / Amplify Authenticator Components?

I'm using the Amplify authenticator component (described here) with Cognito User Pools.
Right now, adding the basic authenticator to html takes the user through the following process automatically:
1) Sign up
2) Enter verification code sent to email
3) Sign-in: Re-enter user name and password
This is based on just adding to html:
<amplify-authenticator></amplify-authenticator>
So new users sign up, and then right away need to sign in. It would be better if they were automatically signed-in, so that upon entering their verification code they went right into the app. This would be a common authentication flow.
Is there a way to have automatic sign-in like this while still using the authenticator components?
I see a github discussion about this topic here, but it is not resolved.
I have figured it out for my purposes. The key is that the Amplify components (authenticator, as well as the individual components) give out information about the state after the user takes action. You can listen for this info, and then programmatically sign in the user once you get the "signIn" state.
These are the states, as described here (I am using Angular):
'signUp' //when you want to show signUp page
'confirmSignUp' //the user has probably just submitted info for signing up, and now you want to show the "confirm" page--like the page where they can enter a verification code
'signIn' //this is the key for these purposes. This is when you want to show the sign in page. In the basic authenticator structure, this happens just after the user has been signed up. So this is where you can automatically sign in the user with Auth.signIn, like below.
'confirmSignIn' //I assume this is after user has submitted the sign in form and you want a confirm page to show
'signedIn' //presumably after user has been fully signed in (not confirmed)
'forgotPassword' //presumably when the forgotPassword form loads (not confirmed)
'requireNewPassword' //presumably when user clicks 'reset password' (not confirmed)
So, using Authenticator, you can listen for the 'signIn' event and automatically sign in the user then. Note however that, while this will sign in the user automatically, Authenticator may still show the sign in page while this action is being processed. You can hide this page, or just use the individual Amplify components, like I show in #2 below.
Even better would be if Amplify/Cognito could just have an option for the developer to select automatic sign in after sign up when they set up Cognito. Automatic sign in on sign up would be in line with modern authentication practice, and would be better for user flow. I do not find this option anywhere. If anyone at Amplify/Cognito is listening, please consider adding this feature.
Note: There seem to be some issues that can arise when using these components. For example--with the authenticator, if the user submits info to sign up, but then leaves the page before entering their verification code: the next time they try to access the app they may have trouble, because they can't go through the sign up process again (a user has already been created), but they also can't sign in (because they've never verified). Some more discussion on that is here.
Additionally, I have found error messages to be an issue. These Amplify components automatically show error messages, and some of them from Cognito are technical messages I would never want a user to see (stuff that talks about "user id" and lambda functions, depending on the random error). There may be a way to customize these, like described here, but be sure you test a lot of different scenarios to see what might happen in terms of the error messages.
If these issues prove problematic for you (like they have for me), you may want to use your own forms instead, and then use Auth.signIn() and related Amplify methods, instead of these components.
But, for auto-signing-in with Amplify components, here is code that worked for me:
1. Using Amplify's Authenticator component:
html
<amplify-authenticator></amplify-authenticator>
ts:
import { AmplifyService } from 'aws-amplify-angular';
import Auth from '#aws-amplify/auth';
Export class AuthComponent implements OnInit {
state: any;
newUser: any;
username: any;
password: any;
constructor(public amplifyService: AmplifyService){
this.amplifyService.setAuthState(this.authState) //may be not required
this.amplifyService.authStateChange$ //listening for state changes
.subscribe(authState => {
this.state = authState.state
if (this.state === 'confirmSignUp'){
console.log('user just signed up, now on verify code form')
this.newUser = authState.user
this.password = this.newUser.username
let checkPassword = this.newUser.username.password
if (checkPassword != 'undefined') {
this.password = checkPassword
/*Note here: I have coded it this way because it looks like the authenticator runs two events when the user hits "sign up". In the first event, you can get the user's password, to be used in the Auth.signIn() function below. In the second event, you can only get the user's username (and password would show up as undefined if you grabbed it there). So we need a way to get the password from the first event.*/
}
}
if ((this.newUser) && (this.state === 'signIn')){//this.newUser included because otherwise this event will fire anytime the sign in page loads--even for returning users trying to sign in (who you would not want to sign in automatically)
console.log('user has just finished signing up)
Auth.signIn(this.username, this.password).then(()=>{//there might be more parameters, like email, first name and last name, phone number, etc. here--depends on your Cognito settings
console.log('should be signed in now! You can navigate away from this page')
}).catch((error)=>{
console.log('error here = ' + error.message + ', error code = ' + error.code)
})
}
})
}
}
Like I mentioned above, this will show the "sign in" page while the Auth.signIn() function is processing. To avoid that, you could have an *ngIf, saying hide the page when this.state = "signIn".
2. Using Individual Amplify Auth Components:
In the below, the page will load with the sign up form.
Once the user enters their details and clicks sign up, the page will show the "confirm sign up" form, which is where the user enters a verification code that Cognito has sent to him/her (depending on your Cognito settings).
Then, once the user is signed up, you can get the "signIn" state like above, and automatically sign the user in:
html:
<amplify-auth-sign-up [authState]="authState" *ngIf="showSignUp"></amplify-auth-sign-up>
<amplify-auth-confirm-sign-up [authState]="authState" *ngIf="showVerify"></amplify-auth-confirm-sign-up>
ts:
import { AmplifyService } from 'aws-amplify-angular';
import { AuthState } from 'aws-amplify-angular/dist/src/providers';
import Auth from '#aws-amplify/auth';
Export class AuthComponent implements OnInit {
public authState: AuthState
public newUser: any
public username: any
public password: any
public state: any
public showSignUp = true
public showVerify = false
constructor(public amplifyService: AmplifyService) {
this.authState ={//the individual Amplify components require a state be set
user: null,
state: 'signUp'
}
this.amplifyService.setAuthState(this.authState) //this might not be required
this.amplifyService.authStateChange$ //listening for state changes.
.subscribe(authState => {
this.state = authState.state
if (this.state === 'confirmSignUp'){//get change in state
this.newUser = authState.user
this.username = this.newUser.username
let checkPassword = this.newUser.username.password
if (checkPassword != 'undefined') {
this.password = checkPassword
/*Note here: I have coded it this way because it looks like the authenticator runs two events when the user hits "sign up". In the first event, you can get the user's password, to be used in the Auth.signIn() function below. In the second event, you can only get the user's username (and password would show up as undefined if you grabbed it there). So we need a way to get the password from the first event.*/
}
this.authState ={
user: authState.user,
state: 'confirmSignUp'
}
this.showSignUp = false
this.showVerify = true
}
if ((this.newUser) && (this.state === 'signIn')){//this.newUser included because otherwise this event will fire anytime the sign in page loads--even for returning users trying to sign in (who you would not want to sign in automatically)
console.log('user has just finished signing up)
Auth.signIn(this.username, this.password).then(()=>{//there might be more parameters, like email, first name and last name, phone number, etc. here--depends on your Cognito settings
console.log('should be signed in now! You can navigate away from this page')
}).catch((error)=>{
console.log('error here = ' + error.message + ', error code = ' + error.code)
})
}
})
}
}

Ionic 3 app - allow navigation to page if user logged (check on one place, rather on every component)

How can I add check whether user is logged or not and in accordance with that, allow navigation to desired page or not? It wouldn't be good practice to add :
ionViewCanEnter() {
return this.auth.isAuthenticated();
}
check at the top of every component...
I recommend using an authentication token for your user login. This will allow you to locally store as a variable or local storage and you can implement in your service or provider to be used throughout the app. If you're uncertain with how they work there are plenty of resources online, but ultimately it comes down to your back-end server. Here's an example:Auth Token Example
Also, I would recommend you use *ngIf statement blocks in your html pages where the buttons navigate to the pages themselves and throw an alert if the user tries clicking on the button to navigate.
I have some sample code that can help guide you with this as well.
LoginPage.ts
// API POST authentication
this.API.validateUser(form.value).then((result) =>{
form.reset();//clears values of the form after data is saved to array
this.res = JSON.parse(result.toString());//converts result to array
//console.log(this.res);
if(this.res.token!=""){//sets authtoken to local storage
this.storage.set('authToken',this.res.token)
}
//console.log(localStorage);
if(this.res.status == true){
setTimeout(() => {
LoginPage.initialLogin = true;
this.navCtrl.push(MenuPage);
loading.dismiss();
}, 1000);
}
MenuPage.ts
// MenuPage.ts
/* calls local storage once user hits menupage*/
if(LoginPage.initialLogin==true){
//console.log('Initial Login is:',LoginPage.initialLogin);
this.storage.get('authToken').then((data)=>{//grabs local storage auth token
if(data!=null){
//console.log('GET request happened');
this.loggedIn = true;//User is logged in
this.reap.grabAPIData(data);//calls service to grab API data on initial login
}
});
}
else{
this.reap.getLocalStorage();
//console.log('Initial Login is:',LoginPage.initialLogin);
}
MenuPage.html
This is where you can use your value to determine what the user can see or not see. The button can be hidden or you can throw an alert in the .ts file that lets user know they aren't logged in.
<ion-item *ngIf="loggedIn" no-lines>
<button class="menuButton" ion-button large block (tap)="toNexPage()" >
Next page</button>
</ion-item>

preventing user to go back once logged out in laravel 5

I have a logout function like this
public function logout() {
Auth::logout(); // logout user
return Redirect::to('login'); //redirect back to login
}
When logout function is triggered through routes which looks like
Route::get('logout', array(
'uses' => 'userController#logout'
));
user get redirected to the login page. But when goes back using browser, dashboard view gets opened which i don't want to. What can be the best way to prevent users from going back to dashboard once they logged out? Though there are some discussion on this topic, but didn't helped me.
Since you're using the Auth, you can utilise the existing Middleware to stop the back button putting them on dashboard.
Wrap the routes you want to protect with a Route::group
Route::group(['middleware' => 'auth'], function () {
Route::get('dashboard', function () {
// Uses Auth Middleware
});
});
Any attempt to access dashboard without login will put them back on the home page (default location in the middleware). Modify the middleware (found in app/Http/Middleware/Authenticate.php) to change the redirect url.
you need to add a middleware in your dashboard so that even if they press back the button they can go back to the page but can't do anything unless they login again.