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.
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'
});
}