Search code examples
angularoauth-2.0refresh-token

How do I get refresh token for Google Oauth 2.0 in my Angular Application?


I have already found a way to generate access token using ng-gapi, but is there a way in which I can get the refresh token, as the access token is only valid for one hour.


Solution

  • Have you found the solution for this issue? I have been stocked with a similar problem. According to Using OAuth 2.0 for Web Server Applications (Step 5) article, we can get a refresh token from the response of the request to https://oauth2.googleapis.com/token endpoint with authorization code in parameters. This authorization code I got using grantOfflineAccess() method of GoogleAuth object, which returns a promise with this code. I'm not sure if this solution is correct enough, but it works fine for me. Here some methods, I hope it will help you too.

    private tokenRequestParams: TokenReqParams = {
        client_id: AuthService.CLIENT_ID_KEY,
        client_secret: AuthService.CLIENT_SECRET_KEY,
        redirect_uri: 'http://localhost:4200',
        grant_type: 'authorization_code'
      };
    
      /**
       * if a user was logged the method returns user info, if not - checks that if refresh token   has been stored
       * and accordingly to this uses different methods for user sing-in
       * @returns - the data of the authorized user
       */
      public login(): Observable<User> {
        const isUserLoggedIn = this.refreshToken && this.accessToken;
        if (isUserLoggedIn) {
          return this.getUserInfo();
        } else {
          return this.googleAuthService.getAuth().pipe(
            switchMap( auth => {
              return (!this.refreshToken) ? this.firstSignIn(auth) : this.signIn(auth);
            })
          );
        }
      }
      
      
        /**
       * The method makes sign-in action and return's data of the user who was authorized
       * method will be used when grants were allowed after first sign in
       * @params auth - GoogleAuth object
       * @returns - user data
       */
      private firstSignIn(auth: GoogleAuth): Observable<User> {
        return from(auth.grantOfflineAccess()).pipe(
          switchMap(code => this.fetchToken({code: code.code}).pipe(
            map(() => this.signInSuccessHandler(auth.currentUser.get()))
          ))
        );
      }
      
      
        /**
       * The method makes sign-in action and return's data of the user who was authorized
       * method will be used when grants were allowed after first sign in
       * @params auth - GoogleAuth object
       * @returns - user data
       */
      private signIn(auth: GoogleAuth): Observable<User> {
        return from(
          auth.signIn().then(
            (res: GoogleUser) => this.signInSuccessHandler(res),
            err => { throw Error(err); }
          )).pipe(
          map((user: User) => user),
          catchError(() => throwError('login failed'))
        );
      }
    
    
      /**
       * The method fetches access token or both tokens (access and refresh) depending of received options
       * and stores them to local and session storage's
       * @params params - object, that determine which grant of token gets
       * details: https://developers.google.com/identity/protocols/oauth2/web-server#creatingclient
       * @returns - object with token data
       */
      private fetchToken(params: TokenAccessParams | TokenRefreshParams): Observable<Token> {
        const requestParams = {
          ...this.tokenRequestParams,
          ...params
        };
        return this.httpClient.post(this.TOKEN_ENDPOINT, requestParams).pipe(
          tap((res: Token) => {
            const {access_token, refresh_token} = res;
            sessionStorage.setItem(AuthService.SESSION_ST_ACCESS_TOKEN, access_token);
            if (refresh_token) { localStorage.setItem(AuthService.LOCAL_ST_REFRESH_TOKEN, refresh_token); }
          })
        );
      }
    
    
      /**
       * Method use current token to get new token
       * @returns - New token
       */
      private updateAccessToken(): Observable<any> {
        return this.fetchToken({
          refresh_token: this.refreshToken,
          grant_type: 'refresh_token'
        });
      }