Closed ahmadqarshi closed 8 years ago
It won't be added to this library but there might be a module released which handles it. If you'd like to include token refreshing for a mobile app in your own service, take a look at this example for Ionic 2.
@chenkie do you have any tutorial on how to implement the refresh token link you just gave?
@kelvinrolex The example code is very well written and easy to understand. I've implemented it using exactly the same technique used in the example link provided by @chenkie . Just look at the source code in the example and if you need any help please let me know.
Ok, but pls can you just at least post a line of code on how you implemented it, I can continue from there. Thanks.
Below is my modified version example code. There are two functions scheduleRefresh
and startupTokenRefresh
.
In your login function when you are successfully logged-in, call the scheduleRefresh
function. Inside your ngOnInit
of AppComponent
check if your are already authenticated and the token is valid, if yes, then call startupTokenRefresh
.
`
@Injectable()
export class TokenManagementService {
jwtHelper: JwtHelper = new JwtHelper();
refreshSubscription: any;
constructor(private authHttp: AuthHttp, private http: Http) { }
getToken() {
return sessionStorage.getItem('id_token');
}
private getNewJwt() {
let refreshTokenId = localStorage.getItem('refresh-token-id');
var header = new Headers();
header.append('Content-Type', 'application/x-www-form-urlencoded');
let body = 'grant_type=refresh_token&refresh_token=' + refreshTokenId;
return this.http.post('http://localhost:1212121/token', body, { headers: header })
.map((res) => this.processTokenResponse(res))
.catch(HttpExceptions.handleErrors);
}
get isAuthenticated(): boolean {
if (tokenNotExpired(undefined, sessionStorage.getItem('id_token'))) {
return true;
} else {
return false;
}
}
public scheduleRefresh() {
// If the user is authenticated, use the token stream
// provided by angular2-jwt and flatMap the token
let source = this.authHttp.tokenStream.flatMap(
token => {
// The delay to generate in this case is the difference
// between the expiry time and the issued at time
let jwtExp = this.jwtHelper.decodeToken(token).exp;
let iat = new Date(sessionStorage.getItem('.issued')).getTime()/1000;
let refreshTokenThreshold = 10; //seconds
let delay = ((jwtExp - iat) - refreshTokenThreshold) * 1000;
return Observable.interval(delay);
});
this.refreshSubscription = source.subscribe(() => {
this.getNewJwt().subscribe((res) => console.log('-> Refreshed...'),(error) => console.log('Refresh error: '+ JSON.stringify(error)))
});
}
public startupTokenRefresh() {
// If the user is authenticated, use the token stream
// provided by angular2-jwt and flatMap the token
if (this.isAuthenticated) {
let source = this.authHttp.tokenStream.flatMap(
token => {
// Get the expiry time to generate
// a delay in milliseconds
let now: number = new Date().valueOf()/1000;
let jwtExp: number = this.jwtHelper.decodeToken(token).exp;
let iat = new Date(sessionStorage.getItem('.issued')).getTime()/1000;
let refreshTokenThreshold = 10; //seconds
let delay: number = jwtExp - now ;
let totalLife: number = (jwtExp - iat);
(delay < refreshTokenThreshold ) ? delay = 1 : delay = delay - refreshTokenThreshold;
// Use the delay in a timer to
// run the refresh at the proper time
return Observable.timer(delay*1000);
});
// Once the delay time from above is
// reached, get a new JWT and schedule
// additional refreshes
source.subscribe(() => {
this.getNewJwt().subscribe(
(res) => {
console.log('-> Refreshed on startup')
this.scheduleRefresh();
},
(error) => console.log('-> Refresh error:'+ JSON.stringify(error)))
});
}
}
public unscheduleRefresh() {
// Unsubscribe fromt the refresh
if (this.refreshSubscription) {
this.refreshSubscription.unsubscribe();
}
}
public persistTokenInformation(token: string, issuedTime: string, tokenExpiry: string, refreshTokenId: string){
sessionStorage.setItem('id_token', token);
sessionStorage.setItem('.issued', issuedTime);
sessionStorage.setItem('.expires', tokenExpiry);
localStorage.setItem('refresh-token-id', refreshTokenId);
}
private processTokenResponse(res: Response) {
this.persistTokenInformation(res.json().access_token, res.json()['.issued'], res.json()['.expires'], res.json().refresh_token);
return Observable.of(true);
}
}
`
NOTE:- I am generating the access_token in ASP.NET Web API. But somehow the iat
is not populated. I've already posted a question on SO about it. In the mean time for iat
I am using .issued
which I get along with access_token.
Ok thanks...
@ahmadqarshi why do you need both startupTokenRefresh() with an Observable.timer and scheduleRefresh() with Observable.interval???
@ahmadqarshi scheduleRefresh
sets an amount of time until the token needs to be refreshed for the case when the user first authenticates. When the user refreshes the page or closes it and later returns, the amount of time until refresh needs to be calculated as well, but this is a different calculation because it needs to be taken from the time that the app first starts up, hence the startupTokenRefresh
method.
@chenkie thanks for the explanation; just to be sure, if I refresh the page, scheduleRefresh() timer is useless and the App takes a new countdown calculation with startupTokenRefresh() and when it's completed retakes a "full" countdown calling the scheduleRefresh() method, right?
@chenkie please see http://www.isavecost.in/test/. Token is set in localStorage. On browser it works and in mobile it doesn't. Mobile have localStorage enabled. Tried with 0.2.0 version
I stored and consoled the data from localStorage in mobile. It prints; but No JWT present or has expired
comes only on mobile.
Even though this thread is not relevant to my issue, Since you are experience with mobile made me comment here. Thanks
Please don't post unrelated comments, especially on closed issues.
@ahmadqarshi Where in your code do you use unscheduleRefresh()
?
I call unscheduleRefresh() on logout.
Sent from my iPhone
On 27 Jun 2017, at 17:12, n0490b notifications@github.com<mailto:notifications@github.com> wrote:
@ahmadqarshihttps://github.com/ahmadqarshi Where in your code do you use unscheduleRefresh()?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/auth0/angular2-jwt/issues/172#issuecomment-311407536, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AFWO3N5T1sFrb65hRBBmUZeB7j2JjTf_ks5sISnUgaJpZM4KBf9-.
@ahmadqarshi Did you fix the problem with iat
not being populated?
I've used refresh token functionality in Angular 1.x using angular-jwt. However, I don't see this feature available in angular2-jwt.
Is there any plan to implement it for Angular2.