My code is working properly on local environment but notifications arn't working on production. I'm using angular 8. Firebase 7.6.0 is being used.
When I am sending push notification from firebase console, it is working fine but when some request is hitting from live server admin panel then notifications are not sent. Node.js is used for Backend.
constructor(private messagingService: MessagingService){
if ("serviceWorker" in navigator) {
console.log('--------in service qorker condition')
window.addEventListener("load", function() {
navigator.serviceWorker.register("./firebase-messaging-sw.js").then(
function(registration) {
console.log(
"ServiceWorker registration successful with scope: ",
registration.scope
);
},
function(err) {
// registration failed :(
console.log("ServiceWorker registration failed: ", err);
}
);
});
}
}
ngOnInit() {
// const userId = 'user001';
// this.messagingService.requestPermission(userId);
this.messagingService.receiveMessage();
}
Above is app.component.ts constructor call
import { Injectable } from '#angular/core';
import { AngularFireMessaging } from '#angular/fire/messaging';
import { BehaviorSubject } from 'rxjs'
import { AngularFireDatabase } from '#angular/fire/database';
import { AngularFireAuth } from '#angular/fire/auth';
import { take } from 'rxjs/operators';
#Injectable()
export class MessagingService {
token: any = "";
currentMessage = new BehaviorSubject(null);
constructor(private angularFireDB: AngularFireDatabase,
private angularFireAuth: AngularFireAuth,
private angularFireMessaging: AngularFireMessaging) {
this.angularFireMessaging.messaging.subscribe(
(_messaging) => {
_messaging.onMessage = _messaging.onMessage.bind(_messaging);
_messaging.onTokenRefresh = _messaging.onTokenRefresh.bind(_messaging);
}
)
}
updateToken(userId, token) {
// we can change this function to request our backend service
this.angularFireAuth.authState.pipe(take(1)).subscribe(
() => {
const data = {};
data[userId] = token
this.angularFireDB.object('fcmTokens/').update(data)
})
}
requestPermission(userId) {
this.angularFireMessaging.requestToken.subscribe(
(token) => {
console.log(token);
this.token = token;
this.updateToken(userId, token);
},
(err) => {
console.error('Unable to get permission to notify.', err);
}
);
}
receiveMessage() {
this.angularFireMessaging.messages.subscribe((payload: any) => {
if (payload) {
console.log(payload, '----lasjkdfl');
navigator.serviceWorker.ready.then(function(service_worker) {
service_worker.showNotification(payload.notification.title, {
body: payload.notification.body
});
});
console.log("new message received. ", payload);
this.currentMessage.next(payload);
}
else{
console.log("no payload recieved");
}
});
}
}
Above is messaging service
this.messagingService.requestPermission(userId);
this.messagingService.receiveMessage();
this.message = this.messagingService.currentMessage;
Above code is called in login.component.ts
importScripts('https://www.gstatic.com/firebasejs/7.6.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/7.6.0/firebase-messaging.js');
Above is firebase-messaging-sw.js configuration
Related
When the client emits a new message to the server using socket.io, the server sends an acknowledgment of the newly created messageId with the callback fn(). I am able to log the messageId in the service.ts, but cannot figure out a way to "get" the messageId to the component .ts (in order to update the newly created message with an ID). with the way the code is set below, I get an angular error saying I cannot subscribe to this.appService.newMessage(), even though I am returning an Observable of the new message id with of(newMsgId) in service.ts. Pls lmk if I can add any more information to help
server.js
--------
socket.on('newStaffMessage', function (data, fn) {
var msg = new Message({
sender: data.senderId,
content: { text: data.content.text, attachment: null },
dateTime: new Date(),
});
msg.save((err, messageDoc) => {
Conversation.findByIdAndUpdate(
{ _id: data.conversationId },
{
$push: { messages: messageDoc._id },
},
{ new: true },
function (err, convoDoc) {
if (!err) {
User.findById(data.senderId, function (err, userDoc) {
const payload = {
conversationId: convoDoc._id,
_id: messageDoc._id,
content: {
text: msg.content.text,
attachment: msg.content.attachment,
},
dateTime: msg.dateTime,
sender: {
_id: userDoc._id,
firstName: userDoc.firstName,
lastNameInitial: userDoc.lastNameInitial,
},
};
io.in(convoDoc._id).emit('newStaffMessage', payload);
fn({messageId: messageDoc._id});
});
} else {
console.log(err);
}
}
);
});
});
service.ts
----------
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable, Observer, of } from 'rxjs';
import * as io from 'socket.io-client';
#Injectable({
providedIn: 'root',
})
export class AppService {
private socket = io('http://localhost:3000');
constructor(private http: HttpClient) {}
newMessage(msg) {
this.socket.emit('newStaffMessage', msg, (newMsgId) => {
return of(newMsgId);
});
}
component.ts
------------
this.appService.newMessage(newMessage).subscribe(data => {
console.log(data);
})
You should properly convert handling socket.io event with callback to Observable.
I'd suggest you two options here:
1) Leverage Observable constructor or create operator with given subscription function:
import { Observable } from 'rxjs';
...
newMessage(msg) {
return Observable.create(observer => {
this.socket.emit('newStaffMessage', msg, (newMsgId) => {
observer.next(newMsgId);
});
});
}
2) Use dedicated for such purposes RxJS bindCallback function:
import { bindCallback } from 'rxjs';
newMessage(msg) {
return bindCallback(this.socket.emit)('newStaffMessage', msg);
}
I have to make an aplication to upload videos to Vimeo. I got some examples from buddies right here on Stack, but could not make it work.
Here's the code I assempled from another dev:
vimeo.component.html
<form [formGroup]="vimeoUploadForm">
<div class="video-inputs">
<input type="text" placeholder="Vimeo TOKEN key" formControlName="vimeoAPI">
<input type="text" placeholder="Vimeo Video Name" formControlName="vimeoVideoName">
<input type="text" placeholder="Vimeo Video Description" formControlName="vimeoVideoDescription">
<input type="file" (change)="selectFile($event)" multiple #vimeoUpload style="display: none;">
</div>
</form>
vimeo.component.ts
import { Component, OnInit } from '#angular/core';
import { FormControl, FormGroup, Validators } from '#angular/forms';
import { VimeoUploadService } from './services/vimeo-upload.service';
import { HttpEventType, HttpResponse } from '#angular/common/http';
import { map, switchMap } from 'rxjs/operators';
#Component({
selector: 'app-vimeo',
templateUrl: './vimeo.component.html',
styleUrls: ['./vimeo.component.scss']
})
export class VimeoComponent implements OnInit {
public vimeoUploadForm: FormGroup;
private data: any;
public uploadPercent;
// Track upload status by tracking code
// 0 - Not started
// 1 - File chosen
// 2 - Wrong file type
// 3 - Uploading
// 4 - Upload error
// 5 - Upload complete
public uploadStatus: Number = 0;
constructor(
private uploadControl: VimeoUploadService
) { }
selectFile(event): void {
this.uploadVimeoVideo(event.target.files);
}
uploadVimeoVideo(files: FileList): void {
this.uploadStatus = 1;
if (files.length === 0) {
console.log('No file selected!');
return;
}
const file: File = files[0];
const isAccepted = this.checkAllowedType(file.type);
if (isAccepted) {
this.uploadStatus = 1;
const options = {
token: this.getFormValue('vimeoAPI'),
url: 'https://api.vimeo.com/me/videos',
videoName: this.getFormValue('vimeoVideoName'),
videoDescription: this.getFormValue('vimeoVideoDescription')
};
this.uploadControl.createVimeo(options, file.size)
.pipe(
map(data => this.data = data),
switchMap(
() => {
this.uploadControl.updateVimeoLink(this.data.link);
if (this.data.upload.size === file.size) {
return this.uploadControl.vimeoUpload(this.data.upload.upload_link, file);
} else {
this.uploadStatus = 4;
}
}
)
).subscribe(
event => {
if (event.type === HttpEventType.UploadProgress) {
this.uploadPercent = Math.round(100 * event.loaded / event.total);
this.uploadStatus = 3;
} else if (event instanceof HttpResponse) {
this.uploadStatus = 5;
setTimeout(() => {
this.uploadStatus = 0;
}, 5000);
}
},
(error) => {
console.log('Upload Error:', error);
this.uploadStatus = 4;
}, () => {
console.log('Upload done');
}
);
} else {
this.uploadStatus = 2;
}
}
initVimeoForm() {
this.vimeoUploadForm = new FormGroup(
{
vimeoAPI: new FormControl('', [Validators.required]),
vimeoVideoName: new FormControl('', [Validators.required]),
vimeoVideoDescription: new FormControl('', [Validators.required])
}
);
}
// HELPERS
allowUpload(): void {
this.uploadStatus = 0;
}
checkAllowedType(filetype: string): boolean {
const allowed = ['mov', 'wmv', 'avi', 'flv', 'mp4'];
const videoType = filetype.split('/').pop();
return allowed.includes(videoType);
}
getFormValue(selector: string) {
return this.vimeoUploadForm.get(selector).value;
}
ngOnInit() {
// Init Vimeo Data Form
this.initVimeoForm();
// Return Vimeo Link from API response
this.uploadControl.vimeoLinkObs.subscribe(
data => {
console.log(data);
}, error => {
throw new Error(error);
}
);
}
}
vimeo-upload.service.ts
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { HttpClient, HttpEvent, HttpHeaders, HttpParams, HttpRequest } from '#angular/common/http';
#Injectable()
export class VimeoUploadService {
vimeoObsShare: Observable<string>;
vimeoResult: string;
private vimeoLink = new BehaviorSubject('');
vimeoLinkObs = this.vimeoLink.asObservable();
constructor(private http: HttpClient) { }
updateVimeoLink(val) {
this.vimeoLink.next(val);
}
createVimeo(options, fileSize): Observable<any> {
// CUSTOM HEADERS FOR A FIRST INIT CALL
const initHeaders = new HttpHeaders(
{
'Authorization': 'Bearer ' + options.token,
'Content-Type': 'application/json',
'Accept': 'application/vnd.vimeo.*+json;version=3.4'
}
);
// initHeaders.append('Content-Type', 'application/json');
// initHeaders.append('Accept', 'application/vnd.vimeo.*+json;version=3.4');
// CUSTOM INIT BODY
const initBody = {
'upload': {
'approach': 'post',
'size': fileSize
},
"privacy": {
"embed": "private" // public for public video
},
'name': options.videoName,
'description': options.videoDescription
};
if (this.vimeoResult) {
return new Observable<any>(observer => {
observer.next(this.vimeoResult);
observer.complete();
});
} else if (this.vimeoObsShare) {
return this.vimeoObsShare;
} else {
return this.http.post(options.url, initBody, { headers: initHeaders });
}
}
vimeoUpload(url, file: File): Observable<HttpEvent<any>> {
const headers = new HttpHeaders({
'Tus-Resumable': '1.0.0',
'Upload-Offset': '0',
'Content-Type': 'application/offset+octet-stream'
});
const params = new HttpParams();
const options = {
params: params,
reportProgress: true,
headers: headers
};
const req = new HttpRequest('PATCH', url, file, options);
return this.http.request(req);
}
}
Error that I get
headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}
status: 401
statusText: "Authorization Required"
url: "https://api.vimeo.com/me/videos"
ok: false
name: "HttpErrorResponse"
message: "Http failure response for https://api.vimeo.com/me/videos: 401 Authorization Required"
error:
error: "Unable to upload video. Please get in touch with the app's creator."
link: null
developer_message: "The authentication token is missing a user ID and must be provided when uploading a video."
error_code: 8002
But I'm using this token: b43db728079bbdf962e84fd41b3b37b2
That I got on: https://developer.vimeo.com/apps/167964#personal_access_tokens
First off: never disclose your authentication token in public. Depending on the token's scope, someone could use it to access and modify your account, upload videos to your account, and more.
Luckily, it's not a problem with the token in your query -- it only has "public" scope and cannot be used for uploading to Vimeo or to access any private metadata. You can verify a token's scope by making a request to https://api.vimeo.com/oauth/verify with that token (docs).
To upload, you'll need to create a new Authenticated personal access token with the scopes public private create edit upload. From there, use that token to authenticate your POST /me/videos request (docs).
I hope this information helps!
I'm trying to authenticate all the API calls to the backend using an HttpInterceptor in an Ionic 4 project. The token is saved through NativeStorage. The problem occurs when I make the login call. Since there is not yet an available token, NativeStorage returns an error interrupting the chain: NativeStorageError {code: 2, source: "Native", exception: null}
httpConfig.interceptor.ts
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor,
HttpResponse,
HttpErrorResponse
} from '#angular/common/http';
import { Observable, throwError, from } from 'rxjs';
import { map, catchError, switchMap } from 'rxjs/operators';
import { Injectable } from '#angular/core';
import { LoadingController } from '#ionic/angular';
import { NativeStorage } from '#ionic-native/native-storage/ngx';
const TOKEN_KEY = 'auth-token';
#Injectable()
export class HttpConfigInterceptor implements HttpInterceptor {
loaderToShow: any;
loadingPresent = false;
debug = false;
constructor(
public loadingController: LoadingController,
private storage: NativeStorage
)
{ }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return from(this.storage.getItem(TOKEN_KEY))
.pipe(
switchMap(token => {
if (token) {
request = request.clone({ headers: request.headers.set('Authorization', 'Bearer ' + token.access_token) });
}
if (!request.headers.has('Content-Type')) {
request = request.clone({ headers: request.headers.set('Content-Type', 'application/json') });
}
this.showLoader();
return next.handle(request).pipe(
map((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
console.log('event--->>>', event);
}
this.hideLoader();
return event;
}),
catchError((error: HttpErrorResponse) => {
this.hideLoader();
return throwError(error);
})
);
})
);
}
showLoader() {
console.log("show loader");
this.loaderToShow = this.loadingController.create({
message: 'Cargando datos...'
}).then((res) => {
this.loadingPresent = true;
res.present();
res.onDidDismiss().then((dis) => {
console.log('Loading dismissed!');
});
});
}
hideLoader() {
if(this.loadingPresent) {
this.loadingController.dismiss();
this.loadingPresent = false;
}
}
}
auth.service.ts
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Platform } from '#ionic/angular';
import { tap, map } from 'rxjs/operators';
import { NativeStorage } from '#ionic-native/native-storage/ngx';
import { environment } from '../../environments/environment';
import { User } from '../models/user';
import { BehaviorSubject } from 'rxjs';
const TOKEN_KEY = 'auth-token';
#Injectable({
providedIn: 'root'
})
export class AuthService {
isLoggedIn = false;
token:any;
authenticationState = new BehaviorSubject(false);
constructor(
private http: HttpClient,
private storage: NativeStorage,
private plt: Platform
)
{
this.plt.ready().then(() => {
this.checkToken();
});
}
login(login: String, password: String) {
return this.http.post(environment.API_URL + 'auth/login',
{ login: login, password: password }
).pipe(
map(token => {
this.storage.setItem(TOKEN_KEY, token)
.then(
() => {
this.authenticationState.next(true);
},
error => console.error('Error storing item', error)
);
}),
);
}
logout() {
return this.http.get(environment.API_URL + 'auth/logout')
.pipe(
tap(data => {
return this.storage.remove(TOKEN_KEY).then(() => {
this.authenticationState.next(false);
});
})
)
}
isAuthenticated() {
return this.authenticationState.value;
}
checkToken() {
this.storage.getItem(TOKEN_KEY).then(res => {
if (res) {
this.authenticationState.next(true);
}
});
}
}
When I try to login the first time, it returns the "token not found" error by NativeStorage from the interceptor
NativeStorageError {code: 2, source: "Native", exception: null}
you try to access to 'TOKEN_KEY' item when item doesn't exist.
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return from(this.storage.getItem(TOKEN_KEY)) <-- //This causes error
or
checkToken() {
this.storage.getItem(TOKEN_KEY).then(res => { <-- //This causes error
if (res) {
this.authenticationState.next(true);
}
});
}
you must initialize default value for 'TOKEN_KEY' or add if else condition for controlling(checking) token
you can use this.storage.keys list for find your key
other error codes:
NATIVE_WRITE_FAILED = 1
ITEM_NOT_FOUND = 2
NULL_REFERENCE = 3
UNDEFINED_TYPE = 4
JSON_ERROR = 5
WRONG_PARAMETER = 6
the get function from ionic storage return the value as object { value : "token value "}
so access value property from storage result like this
request = request.clone({ headers: request.headers.set('Authorization', 'Bearer ' +
token.value) });
Here's I have attached my code. I have implemented global handler and now I need to extract 'dashboard' from 500 Error on zone.js. How can I get it in the global Handler. Is there any way that I can get my desired output?
import { ErrorHandler, Injectable, Injector, NgZone } from '#angular/core';
import { LocationStrategy, PathLocationStrategy } from '#angular/common';
import { LogService } from './logging-service.service';
import * as StackTrace from 'stacktrace-js';
#Injectable()
export class GlobalErrorHandler implements ErrorHandler {
private errors = new Array<any>();
constructor(public injector: Injector, public zone: NgZone) {
}
public handleError(error: any) {
console.log('Im a global handler', JSON.parse(error));
const logService = this.injector.get(LogService);
const location = this.injector.get(LocationStrategy);
const message = error.message ? error.message : error.toString();
const url = location instanceof PathLocationStrategy
? location.path() : '';
const callbackFun = function (stackframes) {
const stringifiedStack = stackframes.map(function (sf) {
return sf.toString();
}).join('\n');
console.log(stringifiedStack);
};
const errback = function (err) {
console.log(err);
console.log(err.stack);
};
window.onerror = function (msg, file, line, col, error) {
// this.zone.fromError.subscribe(this.onZoneError);
StackTrace.fromError(message).then(callbackFun).catch(errback);
StackTrace.get().then(callbackFun).catch(message);
};
const handleErrorData = {
// Some Json to send to server
};
logService.logError(handleErrorData);
throw error;
}
public onZoneError(error) {
console.log(error);
console.error('Error', error instanceof Error ? error.message : error.toString());
}
}
Implement an HttpInterceptor (requires Angular 4.3.x)
From there listen to errors and extract the request url and split it into its parts.
I have identity successfully authenticating a user, it passes the user back to the main site which runs
<script src="https://cdnjs.cloudflare.com/ajax/libs/oidc-client/1.2.2/oidc-client.min.js"></script>
<h1 id="waiting">Waiting...</h1>
<div id="error"></div>
<script>
new Oidc.UserManager().signinRedirectCallback().then(function (user) {
if (user == null) {
document.getElementById("waiting").style.display = "none";
document.getElementById("error").innerText = "No sign-in request pending.";
}
else {
window.location = "/";
}
})
.catch(function (er) {
document.getElementById("waiting").style.display = "none";
document.getElementById("error").innerText = er.message;
});
</script>
But when it its the home page "/" it keeps going back to unauthenticated because of
import { NgModule } from '#angular/core';
import { RouterModule } from '#angular/router';
import { UniversalModule } from 'angular2-universal';
import { AppComponent } from './components/app/app.component';
import { HomeComponent } from './components/home/home.component';
import { UnauthorizedComponent } from './components/unauthorized/unauthorized.component';
import { AuthService } from './services/shared/auth.service';
import { AuthGuardService } from './services/shared/auth-guard.service';
#NgModule({
bootstrap: [ AppComponent ],
declarations: [
AppComponent,
HomeComponent,
UnauthorizedComponent
],
imports: [
UniversalModule, // Must be first import. This automatically imports BrowserModule, HttpModule, and JsonpModule too.
RouterModule.forRoot([
{
path: '', redirectTo: 'home', pathMatch: 'full'
},
{
path: 'home',
component: HomeComponent,
canActivate: [AuthGuardService]
},
{
path: 'unauthorized',
component: UnauthorizedComponent
}
])
],
providers: [AuthService, AuthGuardService]
})
export class AppModule {
}
Where AuthGuard is
import { Injectable } from '#angular/core';
import { CanActivate, Router } from '#angular/router';
import { AuthService } from './auth.service';
#Injectable()
export class AuthGuardService implements CanActivate {
constructor(private authService: AuthService, private router: Router) {
}
canActivate() {
if (this.authService.loggedIn)
{
alert("this"); //<--- never happens
return true;
}
alert(this.authService.loggedIn); //<--- always false, happens before everything else?
this.router.navigate(['unauthorized']);
}
}
And where AuthService is
import { Injectable, EventEmitter } from '#angular/core';
import { Http, Headers, RequestOptions, Response } from '#angular/http';
import { Observable } from 'rxjs/Rx';
import { UserManager, Log, MetadataService, User } from 'oidc-client';
#Injectable()
export class AuthService {
mgr: UserManager = new UserManager(settings);
userLoadededEvent: EventEmitter<User> = new EventEmitter<User>();
currentUser: User;
loggedIn: boolean = false;
authHeaders: Headers;
constructor(private http: Http) {
this.mgr.getUser()
.then((user) => {
if (user) {
this.loggedIn = true;
alert("loggedin"); //<--- Happens all the time
this.currentUser = user;
this.userLoadededEvent.emit(user);
}
else {
this.loggedIn = false;
}
})
.catch((err) => {
this.loggedIn = false;
});
this.mgr.events.addUserUnloaded((e) => {
this.loggedIn = false;
});
}
clearState() {
this.mgr.clearStaleState().then(function () {
console.log("clearStateState success");
}).catch(function (e) {
console.log("clearStateState error", e.message);
});
}
getUser() {
this.mgr.getUser().then((user) => {
console.log("got user", user);
this.userLoadededEvent.emit(user);
}).catch(function (err) {
console.log(err);
});
}
removeUser() {
this.mgr.removeUser().then(() => {
this.userLoadededEvent.emit(null);
console.log("user removed");
}).catch(function (err) {
console.log(err);
});
}
startSigninMainWindow() {
this.mgr.signinRedirect({ data: 'some data' }).then(function () {
console.log("signinRedirect done");
}).catch(function (err) {
console.log(err);
});
}
endSigninMainWindow() {
this.mgr.signinRedirectCallback().then(function (user) {
console.log("signed in", user);
}).catch(function (err) {
console.log(err);
});
}
startSignoutMainWindow() {
this.mgr.signoutRedirect().then(function (resp) {
console.log("signed out", resp);
setTimeout(5000, () => {
console.log("testing to see if fired...");
})
}).catch(function (err) {
console.log(err);
});
};
endSignoutMainWindow() {
this.mgr.signoutRedirectCallback().then(function (resp) {
console.log("signed out", resp);
}).catch(function (err) {
console.log(err);
});
};
/**
* Example of how you can make auth request using angulars http methods.
* #param options if options are not supplied the default content type is application/json
*/
AuthGet(url: string, options?: RequestOptions): Observable<Response> {
if (options) {
options = this._setRequestOptions(options);
}
else {
options = this._setRequestOptions();
}
return this.http.get(url, options);
}
/**
* #param options if options are not supplied the default content type is application/json
*/
AuthPut(url: string, data: any, options?: RequestOptions): Observable<Response> {
let body = JSON.stringify(data);
if (options) {
options = this._setRequestOptions(options);
}
else {
options = this._setRequestOptions();
}
return this.http.put(url, body, options);
}
/**
* #param options if options are not supplied the default content type is application/json
*/
AuthDelete(url: string, options?: RequestOptions): Observable<Response> {
if (options) {
options = this._setRequestOptions(options);
}
else {
options = this._setRequestOptions();
}
return this.http.delete(url, options);
}
/**
* #param options if options are not supplied the default content type is application/json
*/
AuthPost(url: string, data: any, options?: RequestOptions): Observable<Response> {
let body = JSON.stringify(data);
if (options) {
options = this._setRequestOptions(options);
}
else {
options = this._setRequestOptions();
}
return this.http.post(url, body, options);
}
private _setAuthHeaders(user: any) {
this.authHeaders = new Headers();
this.authHeaders.append('Authorization', user.token_type + " " + user.access_token);
this.authHeaders.append('Content-Type', 'application/json');
}
private _setRequestOptions(options?: RequestOptions) {
if (options) {
options.headers.append(this.authHeaders.keys[0], this.authHeaders.values[0]);
}
else {
options = new RequestOptions({ headers: this.authHeaders, body: "" });
}
return options;
}
}
const settings: any = {
authority: 'http://localhost:5000/',
client_id: 'js',
redirect_uri: 'http://localhost:38881/auth',
post_logout_redirect_uri: 'http://localhost:38881/',
response_type: 'id_token token',
scope: 'openid profile api',
silent_redirect_uri: 'http://localhost:38881',
automaticSilentRenew: true,
//silentRequestTimeout:10000,
filterProtocolClaims: true,
loadUserInfo: true
};
The problem is that any attempt to go to home or / results in going to unauthorized even though alert("loggedin"); happens
It seems like
alert(this.authService.loggedIn); //<--- always false, happens before everything else, which is the issue why is canactive going even though the result from authservice hasn't returned
I had the same issue. The problem is that the Promise in the AuthService constructor is resolved after AuthGuardService checks whether the user is logged in. To fix this I created a new function in the AuthService:
isLoggedIn(): Observable<boolean> {
return Observable.fromPromise(this.mgr.getUser()).map<User, boolean>((user) => {
if (user) return true;
else return false;
});
}
Then, rewrite the canActivate function of the AuthGuardService to use the isLoggedIn() function instead of relying on the AuthService constructor:
canActivate() {
let self = this;
let isloggedIn = this.authService.isLoggedIn();
isloggedIn.subscribe((loggedin) => {
if(!loggedin){
self.router.navigate(['unauthorized']);
}
});
return isloggedIn;
}
This canActivate implementation returns an Observable instead of a boolean, to let it wait for the Promise in the AuthService to complete. There is also a subscription so we can decide whether to redirect to unauthorized or not.
Also see this issue: https://github.com/jmurphzyo/Angular2OidcClient/issues/21