{"action":"created","issue":{"url":"https://api.github.com/repos/auth0/angular2-jwt/issues/270","repository_url":"https://api.github.com/repos/auth0/angular2-jwt","labels_url":"https://api.github.com/repos/auth0/angular2-jwt/issues/270/labels{/name}","comments_url":"https://api.github.com/repos/auth0/angular2-jwt/issues/270/comments","events_url":"https://api.github.com/repos/auth0/angular2-jwt/issues/270/events","html_url":"https://github.com/auth0/angular2-jwt/issues/270","id":200403101,"number":270,"title":"TokenStream subject","user":{"login":"TMaster","id":7823319,"avatar_url":"https://avatars.githubusercontent.com/u/7823319?v=3","gravatar_id":"","url":"https://api.github.com/users/TMaster","html_url":"https://github.com/TMaster","followers_url":"https://api.github.com/users/TMaster/followers","following_url":"https://api.github.com/users/TMaster/following{/other_user}","gists_url":"https://api.github.com/users/TMaster/gists{/gist_id}","starred_url":"https://api.github.com/users/TMaster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TMaster/subscriptions","organizations_url":"https://api.github.com/users/TMaster/orgs","repos_url":"https://api.github.com/users/TMaster/repos","events_url":"https://api.github.com/users/TMaster/events{/privacy}","received_events_url":"https://api.github.com/users/TMaster/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2017-01-12T15:50:46Z","updated_at":"2017-01-12T16:41:24Z","closed_at":null,"body":"Hi,\r\n\r\nI'm using the library for sending authorized requests to a Node server.\r\n\r\nI struggled a bit with refreshing the token when it's about to expire.\r\n\r\nAfter a long long long while I managed to do so, (I based my solution on[ this suggestion ](https://github.com/auth0/angular2-jwt/issues/15))\r\n\r\nHowever I'm not fully satisfied with my solution. as was suggested in the above link I used the `Auth.tokenStream` but it works differently than I expected.\r\n\r\nFrom Examining the code, I saw this.\r\n\r\n```javascript\r\n public tokenStream: Observable<string>;\r\n\r\n  constructor(options: AuthConfig, private http: Http, private defOpts?: RequestOptions) {\r\n    this.config = options.getConfig();\r\n\r\n    this.tokenStream = new Observable<string>((obs: any) => {\r\n      obs.next(this.config.tokenGetter());\r\n    });\r\n  }\r\n```\r\n\r\nAs I understand it the `tokenStream` will be called only once when constructing the`AuthHttp` (and getting the token).\r\n\r\nHaving that, I believe this stream should represent the currently used token and should look like this:\r\n\r\n\r\n```javascript\r\n private tokenSubject : Subject<string>; // Manages all new tokens\r\n public tokenStream: Observable<string>; \r\n private lastKnownToken : string; // Contains the last known token\r\n \r\n constructor(options: AuthConfig, private http: Http, private defOpts?: RequestOptions) {\r\n    this.config = options.getConfig();\r\n    \r\n     this.tokenSubject = new Subject<string>(); // A subject to publish new tokens\r\n     \r\n     this.lastKnownToken = this.config.tokenGetter();  // Gets the token and stores it in lastKnownToken.\r\n     this.tokenStream = this.tokenSubject.asObservable(); //Now the tokenStream is listening to the tokenSubject. \r\n\r\n     this.tokenSubject.next(this.lastKnownToken); // Publishing new notification about the currently used token.\r\n  }\r\n```\r\n\r\nIn this snippet you can see that instead of managing the actual `tokenStream` we manage the underlying `subject`. (to support backward comparability on construction time we are  publishing the resolved token).\r\n\r\nAnother modification is in the `request()` method: \r\n\r\n\r\n```javascript\r\npublic request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {\r\n\r\n     //Code was  emitted for readability\r\n    let token: string | Promise<string> = this.config.tokenGetter();\r\n    if (token instanceof Promise) {\r\n      return Observable.fromPromise(token).mergeMap((jwtToken: string) => {\r\n\r\n        this.changeTokenIfNeeded(jwtToken); //This is new!!!\r\n\r\n        this.requestWithToken(req, jwtToken)\r\n      });\r\n    } else {\r\n      this.changeTokenIfNeeded(token);//This is new!!!\r\n\r\n      return this.requestWithToken(req, token);\r\n    }\r\n  }\r\n```\r\n\r\nIn this method I just add a call to `changeTokenIfNeeded()` method, which should have the following implementation: \r\n\r\n```javascript\r\n private changeTokenIfNeeded(token: string) {\r\n    if (token !== this.lastKnownToken) { \r\n      this.lastKnownToken = token;  //Replacing the lastKnownToken\r\n\r\n      this.tokenSubject.next(token); //Publishing a notification with the new token.\r\n    }\r\n  }\r\n```\r\n\r\n### Put it all up together\r\n\r\n1. When constructing the AuthHttp class: the resolved token is stored in `lastKnownToken` and it is published using the `tokenSubject` to the `tokenStream`\r\n2. When executing an authenticated HTTP request the `changeTokenIfNeeded()` method is called.\r\n3. The `changeTokenIfNeeded()` method checks if the token has been changed, if so it publishes the new token using the `tokenSubject` to the `tokenStream` (and of course store the new token in `this.lastKnownToken`.)\r\n\r\n### How it affects the user?\r\n\r\nWhen the user will subscribe to the `tokenStream` it will get notified on every new token the AuthHttp uses.\r\n\r\n\r\nWhat do you think of my proposal?\r\n\r\nThanks\r\n"},"comment":{"url":"https://api.github.com/repos/auth0/angular2-jwt/issues/comments/272214021","html_url":"https://github.com/auth0/angular2-jwt/issues/270#issuecomment-272214021","issue_url":"https://api.github.com/repos/auth0/angular2-jwt/issues/270","id":272214021,"user":{"login":"escardin","id":12631891,"avatar_url":"https://avatars.githubusercontent.com/u/12631891?v=3","gravatar_id":"","url":"https://api.github.com/users/escardin","html_url":"https://github.com/escardin","followers_url":"https://api.github.com/users/escardin/followers","following_url":"https://api.github.com/users/escardin/following{/other_user}","gists_url":"https://api.github.com/users/escardin/gists{/gist_id}","starred_url":"https://api.github.com/users/escardin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/escardin/subscriptions","organizations_url":"https://api.github.com/users/escardin/orgs","repos_url":"https://api.github.com/users/escardin/repos","events_url":"https://api.github.com/users/escardin/events{/privacy}","received_events_url":"https://api.github.com/users/escardin/received_events","type":"User","site_admin":false},"created_at":"2017-01-12T16:41:24Z","updated_at":"2017-01-12T16:41:24Z","body":"practically? none really. It would just give you a properly observable token stream. AuthHttp doesn't care, it only wants the latest one at the time of request. If you let it fetch from local storage and you push it into local storage, it'll work just fine. Even for refresh tokens, it's better to just wrap AuthHttp and issue a retry after fetching and saving fresh token."}}
{"actor":{"display_login":"escardin"}}