Hello,
I need to implements an authentication system with ionic2 as explain in your article :
https://auth0.com/blog/ionic-2-authentication-how-to-secure-your-mobile-app-with-jwt/
I have used the node server added on the article and i can send some request for ask token, create user, and get quotes.
When i try to login with my Ionic app i have a weird bug :
"Error: JWT must have 3 parts"
I have create a form login like this
<ion-list>
<ion-item>
<ion-label floating>Username</ion-label>
<ion-input [(ngModel)]="username" type="text"></ion-input>
</ion-item>
<ion-item>
<ion-label floating>Password</ion-label>
<ion-input [(ngModel)]="password" type="password"></ion-input>
</ion-item>
</ion-list>
<div padding>
<button primary block (click)="login()">Sign In</button>
</div>
and my ts file
login() {
console.log('function login called !');
let credentials = {
username: this.username,
password: this.password,
};
console.log(credentials);
this.http.post(`http://localhost:3001/sessions/create`, JSON.stringify(credentials), {headers: this.contentHeader})
.map(res => res.json())
.subscribe(
data => this.authSuccess(data),
err => console.log(err),
() => console.log('login completed !')
);
}
authSuccess(token) {
console.log('function authSuccess called !');
console.log(token);
// token showed
// "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6IlF1b3ZhbmRpdXMiLCJleHRyYSI6IiIsImlkIjoyLCJpYXQiOjE0NzQwMzA1MzYsImV4cCI6MTQ3NDA0ODUzNn0.o_q9lpgE-gRnjQO7rHBrw6yL0aJ7NYv_6C8nE7N-r-c"
this.error = null;
this.local.set('id_token', token);
console.log(this.jwtHelper);
console.log(token);
this.user = this.jwtHelper.decodeToken(token).username;
console.log("user : " + this.user);
}
it seems the token is good, with 3 dots for 3 parts ?_?
I don't understand what is wrong ?
I have checked with jwt.io, theses tokens are good
up ?
I have checked my tokens with jwt.io and there are good.
So why this function decodeToken has printed this error ?
it's possible that you have something like undefined in your local storage from a bad login. Can you make sure that your local storage is clear?
Thx for your answer.
Yes i have checked the localstorage and the sessions storage, all are clear. I have add the logout function on constructor for this test.
I have add the code below :
authSuccess(token) {
console.log('function authSuccess called !');
console.log(token);
// "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6IlF1b3ZhbmRpdXMiLCJleHRyYSI6IiIsImlkIjoyLCJpYXQiOjE0NzQwMzA1MzYsImV4cCI6MTQ3NDA0ODUzNn0.o_q9lpgE-gRnjQO7rHBrw6yL0aJ7NYv_6C8nE7N-r-c"
this.error = null;
this.local.set('id_token', token);
console.log(this.jwtHelper);
console.log(token);
var i;
for (i = 0; i < localStorage.length; i++) {
console.log(localStorage.key(i) + "=[" + localStorage.getItem(localStorage.key(i)) + "]");
}
this.user = this.jwtHelper.decodeToken(token).username;
console.log(this.user);
}
And the return of console
Object {id_token: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZ鈥yOH0.gXRSckPSI5emMWRYzbBpmi7cR585Ec0pZEE95IFjgUk"}
id_token=[[object Object]]
So i change
this.user = this.jwtHelper.decodeToken(token.id_token).username;
The function login has been finish, i see in console my log (function login complete)
But the same error has printed
browser_adapter.js:84 EXCEPTION: Error in build/pages/profile/profile.html:10:13BrowserDomAdapter.logError @ browser_adapter.js:84BrowserDomAdapter.logGroup @ browser_adapter.js:94ExceptionHandler.call @ exception_handler.js:65(anonymous function) @ application_ref.js:337schedulerFn @ async.js:139SafeSubscriber.__tryOrUnsub @ Subscriber.js:225SafeSubscriber.next @ Subscriber.js:174Subscriber._next @ Subscriber.js:124Subscriber.next @ Subscriber.js:88Subject._finalNext @ Subject.js:128Subject._next @ Subject.js:120Subject.next @ Subject.js:77EventEmitter.emit @ async.js:127onError @ ng_zone.js:124onHandleError @ ng_zone_impl.js:74ZoneDelegate.handleError @ zone.js:327Zone.runTask @ zone.js:259ZoneTask.invoke @ zone.js:423
browser_adapter.js:84 ORIGINAL EXCEPTION: Error: JWT must have 3 partsBrowserDomAdapter.logError @ browser_adapter.js:84ExceptionHandler.call @ exception_handler.js:74(anonymous function) @ application_ref.js:337schedulerFn @ async.js:139SafeSubscriber.__tryOrUnsub @ Subscriber.js:225SafeSubscriber.next @ Subscriber.js:174Subscriber._next @ Subscriber.js:124Subscriber.next @ Subscriber.js:88Subject._finalNext @ Subject.js:128Subject._next @ Subject.js:120Subject.next @ Subject.js:77EventEmitter.emit @ async.js:127onError @ ng_zone.js:124onHandleError @ ng_zone_impl.js:74ZoneDelegate.handleError @ zone.js:327Zone.runTask @ zone.js:259ZoneTask.invoke @ zone.js:423
browser_adapter.js:84 ORIGINAL STACKTRACE:BrowserDomAdapter.logError @ browser_adapter.js:84ExceptionHandler.call @ exception_handler.js:77(anonymous function) @ application_ref.js:337schedulerFn @ async.js:139SafeSubscriber.__tryOrUnsub @ Subscriber.js:225SafeSubscriber.next @ Subscriber.js:174Subscriber._next @ Subscriber.js:124Subscriber.next @ Subscriber.js:88Subject._finalNext @ Subject.js:128Subject._next @ Subject.js:120Subject.next @ Subject.js:77EventEmitter.emit @ async.js:127onError @ ng_zone.js:124onHandleError @ ng_zone_impl.js:74ZoneDelegate.handleError @ zone.js:327Zone.runTask @ zone.js:259ZoneTask.invoke @ zone.js:423
browser_adapter.js:84 Error: JWT must have 3 parts
at JwtHelper.decodeToken (angular2-jwt.js:192)
at JwtHelper.getTokenExpirationDate (angular2-jwt.js:202)
at JwtHelper.isTokenExpired (angular2-jwt.js:211)
at Object.tokenNotExpired (angular2-jwt.js:230)
at Function.AuthService.authenticated (auth.ts:9)
at DebugAppView._View_ProfilePage0.detectChangesInternal (ProfilePage.template.js:173)
at DebugAppView.AppView.detectChanges (view.js:243)
at DebugAppView.detectChanges (view.js:348)
at DebugAppView.AppView.detectViewChildrenChanges (view.js:269)
at DebugAppView.AppView.detectChangesInternal (view.js:254)
And on the view, the block
<ion-content *ngIf="auth.authenticated()" padding>
logged as {{ user }}
</ion-content>
has not displayed, i see my form login
Since you're using Ionic 2, have you tried using the promise-based Storage?
...
this.local.get('id_token').then(token => {
this.user = this.jwtHelper.decodeToken(token).username;
console.log(this.user);
});
...
A last weird thing
I follow your recommandation, and i write this
authSuccess(token) {
console.log('function authSuccess called !');
console.log(token);
this.error = null;
this.local.set('id_token', token.id_token);
this.local.get('id_token').then(token => {
console.log('*************************' + token + '*****************************');
this.user = this.jwtHelper.decodeToken(token).username;
});
console.log(this.user);
}
my console doesn't print error, and my view doesn't print my login form
very thanks for this =)
but the console log inside the promise as printed after the success of login function ? should i add a delay for promise ? i don't see my text on view "logged as {{ user }}
It could be a scoping issue with this on your user depending on how you have things set up.
YYYYYYYYYYYYYYEEEEEEEEEEEEEESSSSSSSSSSSSSSSSSSSS
very thanks =) it seems my login work. i have change my view, and declare user as public.
I could see my view as i'm authenticated
I test now to make some request with this authentication =)
Very very thanks @chenkie
no prob!
@chenkie how could I use tokenNotExpired with ionic2 storage promise?
@chenkie @Quovandius , how did you set your user to public? I am running into this same issue:
Object {access_token: "7Uph1sWst....
ERRR
JWT must have 3 parts
at JwtHelper.decodeToken (angular2-jwt.js:192)