Reputation: 81
I have this requirement for my website. The website will be a SPA built with Angular 2. What I want is that the user can login using Google, Facebook, Twitter oauth.
I can setup the oauth on the node server, but the problem is how do I allow login through angular 2 app.
In the angular 2 app if when the user clicks facebook signin option, I cant redirect the user as then I lose the state of my application.
I dont know if this is a very beginner problem. Can anyone help me with the flow of what happens in angular 2 + node oauth
Upvotes: 1
Views: 967
Reputation: 9875
You are going to want to setup routes in the angular app to handle the front end of your application. Then create a service to handle the auth0 authentication of the application,
This is a overview of setting up a secure set of routes and a public set of routes in your app. Once someone logs in with oauth they will be forwarded to the secure routes.
So starting out here is the routes. We will specify a secure and public in the app.routing.ts file
Routes
const APP_ROUTES: Routes = [
{ path: '', redirectTo: '/home', pathMatch: 'full', },
{ path: '', component: PublicComponent, data: { title: 'Public Views' }, children: PUBLIC_ROUTES },
{ path: '', component: SecureComponent, canActivate: [Guard], data: { title: 'Secure Views' }, children: SECURE_ROUTES }
];
Ok so now that you have that. You can create a templates directory. Inside create secure.component and public.component. Then I create a directory called secure and one called public which I put all of my components dependent on the authentication level to access them. I also add their routes to a file in those directories to keep everything separate.
Notice in my routes above I have the [Guard] setup on the secure. This will block anyone from going to the secure routes without authentication.
Here is an example of what that guard looks like.
import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Auth } from './auth.service';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class Guard implements CanActivate {
constructor(protected router: Router, protected auth: Auth ) {}
canActivate() {
if (localStorage.getItem('access_token')) {
// logged in so return true
return true;
}
// not logged in so redirect to login page
this.router.navigate(['/home']);
return false;
}
}
Now that we have that we have the routes secured with Guard. We can setup the auth0
client.
Create a config file with your credentials you get from auth0
interface AuthConfiguration {
clientID: string,
domain: string,
callbackURL: string
}
export const myConfig: AuthConfiguration = {
clientID: 'clietnifherefromauth0',
domain: 'username.auth0.com',
// You may need to change this!
callbackURL: 'http://localhost:3000/endpoint/'
};
Then to actually authenticate someone. Receive their data and save the token as well as their data to the local storage. Also provide a logout function and a check to make sure they are logged in.
import { Injectable } from '@angular/core';
import { tokenNotExpired, JwtHelper } from 'angular2-jwt';
import { Router } from '@angular/router';
import { myConfig } from './auth.config';
declare var Auth0Lock: any;
var options = {
theme: {
logo: '/img/logo.png',
primaryColor: '#779476'
},
languageDictionary: {
emailInputPlaceholder: "[email protected]",
title: "Login or SignUp"
},
};
@Injectable()
export class Auth {
lock = new Auth0Lock(myConfig.clientID, myConfig.domain, options, {});
userProfile: Object;
constructor(private router: Router) {
this.userProfile = JSON.parse(localStorage.getItem('profile'));
this.lock.on('authenticated', (authResult: any) => {
localStorage.setItem('access_token', authResult.idToken);
this.lock.getProfile(authResult.idToken, (error: any, profile: any) => {
if (error) {
console.log(error);
return;
}
localStorage.setItem('profile', JSON.stringify(profile));
this.userProfile = profile;
this.router.navigateByUrl('/CHANGETHISTOYOURROUTE');
});
this.lock.hide();
});
}
public login() {
this.lock.show();
}
private get accessToken(): string {
return localStorage.getItem('access_token');
}
public authenticated(): boolean {
try {
var jwtHelper: JwtHelper = new JwtHelper();
var token = this.accessToken;
if (jwtHelper.isTokenExpired(token))
return false;
return true;
}
catch (err) {
return false;
}
}
public logout() {
localStorage.removeItem('profile');
localStorage.removeItem('access_token');
this.userProfile = undefined;
this.router.navigateByUrl('/home');
};
}
Make sure to go into your auth0 dashboard and select the social links you want. In your case facebook twitter and Google. Then when someone activates the widget those three will appear.
So all we have to do now is show the widget when someone clicks login,
html will show a login link. But if they are logged in it will show a bit of information about them instead.
<ul class="nav navbar-nav pull-right">
<li class="nav-item">
<a class="nav-link" (click)="auth.login()" *ngIf="!auth.authenticated()">Login / SignUp</a>
<a class="aside-toggle" href="#" role="button" aria-haspopup="true" aria-expanded="false" *ngIf="auth.authenticated()">
<span *ngIf="auth.authenticated() && auth.userProfile" class="profile-name">{{auth.userProfile.nickname}}</span>
<span *ngIf="!auth.authenticated() && !auth.userProfile" class="profile-name">Account</span>
<i class="icon-bell"></i><span class="tag tag-pill tag-danger profile-alerts">5</span>
<img *ngIf="auth.authenticated() && auth.userProfile" [src]="auth.userProfile.picture" class="img-avatar profile-picture" alt="User profile picture">
<img *ngIf="!auth.authenticated() && !auth.userProfile" src="/img/avatars/gravatar-default.png" alt="Default profile-picture">
</a>
</li>
</ul>
Let me know if anything is not clear. I would be glad to help.
Upvotes: 2