amazon-archives / aws-cognito-angular-quickstart

An Angular(v5)-based QuickStart single-page app utilizing Amazon Cognito, S3, and DynamoDB (Serverless architecture)
https://cognito.budilov.com
Apache License 2.0
689 stars 302 forks source link

How to get the Token for API Call #106

Closed Nicosoft closed 7 years ago

Nicosoft commented 7 years ago

Hi there,

I am trying to create a new method in /serverice/cognito.service.ts that returns the token JWT. I need the token because I want to call a method in AWS Gateway. This method has a Authorization (Cognito User Pool).

So I wrote the following function in /serverice/cognito.service.ts getToken() { let token = this.getCurrentUser().getSignInUserSession().getAccessToken().getJwtToken(); console.log('### TOKEN', token); return token; } Unfortunately this generates an error:

screen shot 2017-09-08 at 4 50 45 pm

So my question is: How do I correctly get the Token?

Thank for your help!

Nr18 commented 7 years ago

I added the generated api sdk to the project and using that for now, i would love to see this in a more native typescript/angular way.... but it's not my expertise.

vbudilov commented 7 years ago

Here's the code: https://github.com/awslabs/aws-cognito-angular2-quickstart/blob/0bb50037076c7954c6c9f0451831a987af3f9dfb/src/app/service/cognito.service.ts#L122

Nicosoft commented 7 years ago

Thank you for your answer @vbudilov .

I use this function (getIdToken()) to get the token. Token that I provide in my call to the API gateway. And guess what ... It works!

Here the service I created:

import { Injectable } from '@angular/core';
import { Http, Response, RequestOptions, Headers} from '@angular/http';
import { Businessunit } from '../models/businessunit';
import { Observable } from 'rxjs/Observable';
import {Callback, CognitoUtil} from '../service/cognito.service';
import 'rxjs/Rx';

@Injectable()
export class BuService {

  private urlapi = 'https://###';
  private uri = 'businessunits';
  public idToken: string;

  constructor(
    private http: Http,
    public cognitoUtil: CognitoUtil) {
      this.cognitoUtil.getIdToken(new IdTokenCallback(this));
  }

  // Get all the divisions
  getBusinessunits(): Observable<Response> {

    let header = new Headers();
    header.append('Access-Control-Allow-Origin', '*');
    header.append('Content-Type', 'application/json');
    header.append('Authorization', this.idToken);
    let options = new RequestOptions({ headers : header });
    return this.http.get(this.urlapi + '/' + this.uri, options);
  }

}
export class IdTokenCallback implements Callback {
  constructor(public jwt: BuService) {
  }

  callback() {
  }

  callbackWithParam(result) {
      this.jwt.idToken = result;
  }
}

This documentation helped me a lot as well to know what token I needed to provide (Access Token or ID Token) and how to setup the AWS API Gateway. http://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html

Happy coding!

Nr18 commented 7 years ago

@Nicosoft thanks i'm implementing CloudFormation see #109 and afterwards i want to include a sample on how to use the API Gateway so i'm going to re-use some of your code if thats ok.

kgilper commented 7 years ago

@Nicosoft Thank you for sharing. The only issue I can see with this is that it will expire within an hour.

Nicosoft commented 7 years ago

@kgilper you are right. If you stay on the same page, the token will expired. If you know a better way please share it, otherwise I will when I find it!

kgilper commented 7 years ago

@Nicosoft you could do something like this. I ran it for a few hours calling the function using a timeout. The id token was refreshed as expected and it did not make extraneous calls to amazon.

import {Injectable} from '@angular/core';
import {Observable} from 'rxjs/Rx';
import {Http, Response, Headers, RequestOptions} from '@angular/http';
import {Callback, CognitoUtil} from '../services/cognito.service';

@Injectable()
export class BuService {

  private urlapi = 'https://###';
  private uri = 'businessunits';
  public idToken: string;

  constructor(private http: Http, public cognitoUtil: CognitoUtil, public userParams: UserParametersService) { }

  getToken(): Observable<any> {
    return Observable.create(observer => {
      this.cognitoUtil.getIdToken(new IdTokenCallback(result => {
        observer.next(result);
      }));
    });
  }

  getBusinessunits(): Observable<Response> {
    return this.getToken().flatMap(token => {

      const header = new Headers();
      header.append('Access-Control-Allow-Origin', '*');
      header.append('Content-Type', 'application/json');
      header.append('Authorization', token);
      const options = new RequestOptions({headers: header});

      return this.http.get(this.urlapi + '/' + this.uri, options);
    });
  }
}

export class IdTokenCallback implements Callback {

  _valueReturnFunction: any = null;

  constructor(valueReturnFunction: any) {
    this._valueReturnFunction = valueReturnFunction;
  }

  callback() {
  }

  callbackWithParam(result) {
    this._valueReturnFunction(result);
  }
}
Nicosoft commented 6 years ago

@kgilper , thanks for sharing. I am testing your version right now!

kgilper commented 6 years ago

@Nicosoft Did it work ok?

Nicosoft commented 6 years ago

@kgilper , your version works better than my one. I don't get the 'Expired Token' error message anymore. Thank you again for sharing!

kgilper commented 6 years ago

@Nicosoft cheers to @vbudilov