I have angular 8 application and I am using identity server. And I have a home component and a navbar component. And on a navbar component you have a login button what the user will directed to the login page.
But what I want now is that if you go to home: http://localhost:4200/home. That the use will directly go to the login page.
So this is the home component:
export class HomeComponent implements OnInit {
constructor(public oidSecurityService: OidcSecurityService) {}
ngOnInit() {
this.login();
console.log(this.oidSecurityService.getState);
}
login() {
this.oidSecurityService.authorize();
}
}
And this is the navbar component:
export class NavBarComponent implements OnInit, OnDestroy {
currentUser$: Observable<any> ;
userData: any;
isAuthenticated$: Observable<boolean> ;
isAuthenticated: boolean;
constructor(
public oidSecurityService: OidcSecurityService,
private _oidcConfigService: OidcConfigService,
public platform: Platform
) {}
ngOnInit(): void {
this.isAuthenticated$ = this.oidSecurityService.isAuthenticated$;
this.oidSecurityService.checkAuth().subscribe(auth => {
console.log('is authenticated', auth);
});
this.oidSecurityService.userData$.subscribe(userData => {
console.log(this.userData = userData);
});
this.isAuthenticated$.subscribe((data) => {});
}
ngOnDestroy(): void {}
login() {
this.oidSecurityService.authorize();
console.log(this.oidSecurityService.getState);
}
logout() {
this.oidSecurityService.logoff();
}
get token() {
const claims: any = this.oidSecurityService.getToken();
return claims ? claims : null;
}
}
So when you trigger the login button the user sees the login page.
But so how to trigger directly the login page from home? So if you go to: http://localhost:4200/home user sees directly the login page
So what I have to change?
I don't have login component. I am using Identity server. So this: this.oidSecurityService.authorize(); will go to this page, where user can login:
http://localhost:4430/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3Dcrowd-dashboard%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A4200%26response_type%3Dcode%26scope%3Dopenid%2520profile%2520dashboard-api%26nonce%3Ddde8a3159556f497f4d3cf223540b26a1dYah1g3W%26state%3D90d1eb8c5acbe26ededcbf0a61c4e4da70sjjLw1b%26code_challenge%3DEJ1nAdtWM45Z3IoNnwVZWzAzKTz2xDC1y1c1qi1bwTU%26code_challenge_method%3DS256
You mean like this in ngOninit:
window.location.replace('http://localhost:4430/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3Dcrowd-dashboard%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A4200%26response_type%3Dcode%26scope%3Dopenid%2520profile%2520dashboard-api%26nonce%3D3daf0245322085adfada4bb19abb7da0c8YW1v4iG%26state%3D90d1eb8c5acbe26ededcbf0a61c4e4da70sjjLw1b%26code_challenge%3DQ-R9LMcBmSyrUCS4ZK0WljuA__z2p7S3WMXsFOjMyY0%26code_challenge_method%3DS256');
so this is my guard:
#Injectable({ providedIn: 'root' })
export class AuthorizationGuard implements CanActivate {
constructor(private oidcSecurityService: OidcSecurityService, private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.oidcSecurityService.isAuthenticated$.pipe(
map((isAuthorized: boolean) => {
console.log('AuthorizationGuard, canActivate isAuthorized: ' + isAuthorized);
if (!isAuthorized) {
this.router.navigate(['/unauthorized']);
return false;
}
return true;
})
);
}
}
and this is my app.routing.module.ts:
const routes: Routes = [
{ path: 'home', component: HomeComponent, canActivate: [AuthorizationGuard] },
{ path: '**', redirectTo: 'home' }
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
Use routers and guards as described in
https://itnext.io/handle-restricted-routes-in-angular-with-route-guards-95c93be9d05e
The Guards will instruct the routers when user can access to specific routes.
Also take a look at:
How to check: is the User logged in with angular-6-social-login npm package?
Related
I need a way to update a variable in my header component (always displayed) whenever a param changes in the URL.
My routing:
const routes: Routes = [
{
path: '',
component: DefaultLayoutComponent,
data: {
title: 'Home'
},
children: [
{
path: 'home',
component: HomeComponent
},
{
path: 'dashboard/:id',
component: DashboardComponent,
},
]
},
{path: '**', redirectTo: 'home'}
];
The dashboard component has an ID attached to it and this is what I need to track. In the event a user goes to a page without an ID (such as the home route) I want the ID to show as 0.
I have this working to where it will track the ID as long as they continue to hit routes with an ID but as soon as they navigate to home all tracking is stopped.
header.component
import { Component, Input } from '#angular/core';
import { ClassToggleService, HeaderComponent } from '#coreui/angular-pro';
import { ActivatedRoute } from '#angular/router';
import { Subscription } from 'rxjs';
#Component({
selector: 'app-default-header',
templateUrl: './default-header.component.html',
})
export class DefaultHeaderComponent extends HeaderComponent {
private issuer: Subscription;
constructor(private classToggler: ClassToggleService,
private route: ActivatedRoute) {
super();
}
issuerID: number;
ngOnInit(): void {
this.route.children.forEach(child => {
child.params.subscribe(params => {
const id = params['id'] || 0
console.log('id ' + id)
this.issuerID = id
})
})
}
//To prevent memory leak
ngOnDestroy(): void {
if (this.issuer)
this.issuer.unsubscribe()
}
}
Im am working on an Angular 9 application that uses OneLogin for authentication purposes.
In the auth.component.ts file I have an authentication service that I use in the authentication component:
import { AuthService } from 'path/to/core/services/auth/auth.service';
import { AuthApiService } from 'path/to/core/core/services/auth/auth-api.service';
import { Component, OnInit } from '#angular/core';
import { authCodeFlowConfig } from 'path/to/config/onelogin-api/config-auth.component';
#Component({
selector: 'auth',
templateUrl: './assets/auth.component.html',
styleUrls: ['./assets/auth.component.scss']
})
export class AuthComponent implements OnInit{
constructor(private _authService: AuthService) {
}
startAuthentication() {
this._authService.startAuthentication();
}
ngOnInit(): void {
this.startAuthentication();
}
}
In auth.service.ts I have the startAuthentication() method:
startAuthentication(): Observable<any> {
const {issuer, redirectUri, clientId, responseType, scope} = authCodeFlowConfig;
const url = `someURL`;
this.redirectTo(url);
return of(false);
}
redirectTo(url: string): void {
window.location.href = url;
}
In the app.module.ts file I have this array of routes:
import { AuthService } from './core/services/auth/auth.service';
// more imports
const appRoutes: Routes = [
{
path : 'myroute',
redirectTo: 'myroute'
},
{
path: 'auth',
component: AuthComponent
}
];
In other words, I want the application to reach a certain url if login is successful and otherwise redirect to the login form.
What I want to happen is: when login is sucessful - in other words, when startAuthentication() is executed - there should be a redirect to myroute.
I tried {path: 'auth', component: AuthComponent, startAuthentication:[AuthService]} bit it fails.
What am I doing wrong?
As I don't have any further information about your StartAuthentication method, I'd say that you should inject the router service in your component and navigate using it:
import { Router } from '#angular/router';
...
constructor(
private _authService: AuthService,
private _router: Router) {}
startAuthentication() {
this._authService.startAuthentication();
this._router.navigate(['/', 'myroute']);
}
Tried to follow AuthGuard example available here:
http://www.sparkbit.pl/angular-2-route-guards-real-life-example/
Unfortunately, while trying to implement the ActivationGuard.ts file, I'm receiving few errors.
ERROR in C:/Users/app/src/app/ActivationGuard.ts (6,24): Cannot find name 'ActivatedRouteSna
pshot'.)
C:/Users/app/src/app/ActivationGuard.ts (6,55): Cannot find name 'RouterStateSnapshot'.)
C:/Users/app/src/app/ActivationGuard.ts (13,62): Cannot find name 'CurrentUserService'.)
C:/Users/app/src/app/ActivationGuard.ts (15,31): Cannot find name 'ActivatedRouteSnapshot'.)
C:/Users/app/src/app/ActivationGuard.ts (15,62): Cannot find name 'RouterStateSnapshot'.)
Which basically means that the elements inside the CanActivate interface and inside constructors are not defined.
routing file:
import { WorksheetAccessGuard } from "./ActivationGuard";
const appRoutes: Routes = [
{ path: '', component: LoginComponent },
{ path: 'app', component: AppComponent, canActivate: [WorksheetAccessGuard] },
{ path: '**', redirectTo: '' }
];
My question: From where could I get these missing elements?
Provided image of my IDE: (the red words are the missing ones)
EDIT
I have made a custom service. I'm not sure if its fine or not:
import {Injectable} from '#angular/core';
import {Http} from '#angular/http';
#Injectable()
export class UserAuthenticationService {
isUserAuthenticated: boolean = false;
username: string;
constructor(private http: Http) {
}
authentication() {
this.http.get(`http://localhost/api/auth/isLogged/${this.username}`)
.subscribe(res => {
this.isUserAuthenticated = res.json();
},
err => {
console.error('An error occured.' + err);
});
}
}
Now I'm receiving some error inside the AuthGuard file:
ERROR PIC
**My main goal is checking with every component change (when user navigates over the page) if he is logged or not. If not - return him to the login page.
EDIT2
Can I just post all logic from the service in the AuthGuard file? It will look like:
import {Injectable} from '#angular/core';
import {Router, RouterStateSnapshot, ActivatedRouteSnapshot} from '#angular/router';
import {Observable} from 'rxjs/Observable';
import {UserAuthenticationService} from './UserAuthenticationService';
import {Http} from '#angular/http';
interface CanActivate {
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean>|Promise<boolean>|boolean
}
#Injectable()
export class WorksheetAccessGuard implements CanActivate {
private static username: string;
isUserAuthenticated: boolean = false;
constructor(private router: Router, private userService: UserAuthenticationService, private http: Http) {
}
public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
this.http.get(`http://localhost/api/auth/isLogged/${this.username}`)
.subscribe(res => {
this.isUserAuthenticated = res.json();
},
err => {
console.error('An error occured.' + err);
});
if (!this.isUserAuthenticated) {
this.router.navigate(['/']);
return false;
}
return true;
}
}
RouterStateSnapshot and ActivatedRouteSnapshot are imported from #angular/router, while the currentUser Service is supposed to be your own where you should store the authenticated state of your User (with a boolean for example).
You retrieve an instance of it through Dependency Injection in your guard's constructor like so :
import { CurrentUserService } from './path/to/your/service/file';
import { RouterStateSnapshot, ActivatedRouteSnapshot } from '#angular/router';
constructor(private userService: CurrentUserService)
{}
Your service needs to be provided in your module, (as well as your guard), and you need to have a property like this in your CurrentUserService :
CurrentUserService :
isAuthenticated: boolean = false;
That way, when you log in from your Login Component (I assume you have one), you can set the service property to true :
LoginComponent :
import { CurrentUserService } from './path/to/your/service/file';
constructor(private userService: CurrentUserService)
{}
login() {
... // Your existing code where you login on form submit or anything
this.userService.isAuthenticated = true;
}
EDIT :
Check out my example, it should fit for yours.
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
if (!this.authService.isAuthenticated) {
// Deny navigation and redirect to login
this.router.navigate(['/path/to/login']);
return false;
}
// Allow navigation (be careful that the guard always resolve a value)
return true;
}
I am trying to create a website backend for which I need User Authentication in Angular 2. But I am unable to resolve some of issue, this is what I am doing.
This is my routing file.
const appRoutes: Routes = [
{
path: 'admin',
component: AdminloginComponent,
canActivate: [LoggedInGuard]
},
{
path: '',
component: HomepageComponent
},
{
path: '**',
component: OurservicesComponent
},
];
This is my gaurd file: // after successfull login i am setting is_logged_in in local storage.
import { Injectable } from '#angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '#angular/router';
#Injectable()
export class LoggedInGuard implements CanActivate {
constructor(private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if(localStorage.getItem("is_logged_in"))
{
this.router.navigate(['/admin/dashboard']);
return true;
}
return false;
}
}
** My issue is that when the url is /admin canActivate comes into action and if I get local storage I am navigating to admin/dashboard.
But if user is logged out then in this case on /admin their should be loginform, but if I navigate to /admin if not logged in then it comes into canActivate and again their is nothing in local storage so it goes to admin and so on. So what is the correct way to solve this.
Thanks in advance.
It unclear what exactly you try to accomplish, but redirect with router.navigate should go with return false;, not with return true;
Either
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if(localStorage.getItem("is_logged_in")) {
return true;
}
this.router.navigate(['/admin/dashboard']);
return false;
}
or
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if(localStorage.getItem("is_logged_in")) {
this.router.navigate(['/admin/dashboard']);
return false;
}
return true;
}
I'm having trouble capturing the original navigating route using a guard in Angular 2.
My site consists of a core module protected by an authorization guard, and a login page that's unprotected.
The core module has it's own sub routes defined in it's own app routing file, and any undefined routes are redirected to the root path.
Here's my top level routing module.
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { AuthGuard } from './auth';
const routes: Routes = [
// Login module is public
{ path: 'login', loadChildren: 'app/auth/auth.module#AuthModule' },
// Core route protected by auth guard
{ path: '', loadChildren: 'app/core/core.module#CoreModule', canLoad: [AuthGuard] },
// otherwise redirect to home
{ path: '**', redirectTo: '' }
];
#NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ]
})
export class AppRoutingModule {}
And here is the AuthGuard class.
import { Injectable } from '#angular/core';
import { Router, CanLoad, Route } from '#angular/router';
import { AuthService } from './auth.service';
#Injectable()
export class AuthGuard implements CanLoad {
constructor(
private authService: AuthService,
private router: Router
) {}
canLoad(route: Route): boolean {
this.authService.redirectUrl = `/${route.path}`;
console.log('path:' + route.path);
if (this.authService.isLoggedIn()) {
return true;
} else {
this.router.navigate(['/login']);
return false;
}
}
}
This is a pretty straightforward login/redirect scheme, however the route.path value is always empty, regardless of what URL I navigate to. I have a hunch that it has something to do with the { path: '**', redirectTo: '' } route but I'm not sure.
I don't want to use canActivate because I only want the main module loaded if the user is actually logged in.
What I expected was that if I navigate to /foobar then route.path would be set to foobar in the AuthGuard class but it is not. It is always empty, thus I am unable to do a correct redirect after the user logs in.
Try adding the pathMatch: 'full' like this:
{path: '**', redirectTo: '', pathMatch: 'full'}
or
import {CanActivate, RouterStateSnapshot, ActivatedRouteSnapshot} from "#angular/router";
import { Subscription, Observable } from "rxjs/Rx";
export class HomepageGuard implements CanActivate {
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
console.log(`[homepage.guard.ts]-[canActivate()]`);
console.log(route);
console.log(state);
// are you allowed to continue
return true;
}
}