I'm building a project using angular 5.x and aws-amplify. I successfully managed to sign-up, confirm and sign-in my users via aws-cognito and now, I would like to retrieve user's jwt
to add it at requests header to perform CRUD operations on my dynamoDb collection.
Unluckily, when I try to perform such operation on dynamo I get the following error:
{
"message": "Authorization header requires 'Credential' parameter. Authorization header requires 'Signature' parameter. Authorization header requires 'SignedHeaders' parameter. Authorization header requires existence of either a 'X-Amz-Date' or a 'Date' header. Authorization=xxxxx"
}
I get user's token using the following Cognito.service:
import { Injectable } from '@angular/core';
/** rxjs **/
import { fromPromise } from 'rxjs/observable/fromPromise';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
/** 3rd party **/
import { Auth } from 'aws-amplify';
@Injectable()
export class CognitoService {
getJwtToken(): Observable<any> {
return this.getCurrentSession()
.switchMap((token) => {
return of(token.getIdToken().getJwtToken());
})
}
private getCurrentSession(): Observable<any> {
return fromPromise(Auth.currentSession());
}
}
That get's called by:
this.cognitoService.getJwtToken()
.subscribe((token: string) => {
this.dynamoService.get(
'testResource?id=someValue',
{
Authorization: token
}
)
})
And where Dynamo.service is the following:
import { Injectable } from '@angular/core';
/** rxjs **/
import { fromPromise } from 'rxjs/observable/fromPromise';
import { Observable } from 'rxjs/Observable';
/** 3rd party **/
import { API } from 'aws-amplify';
/** App Environment **/
import { environment } from '../../../environments/environment';
@Injectable()
export class DynamoDBService {
apiName = environment.amplify.API.endpoints[0].name;
get(path: string, headers: any): Observable<any> {
return fromPromise(
API.get(
this.apiName,
path,
{
headers: headers
}
)
);
}
}
My environment looks like:
export const environment = {
production: false,
amplify: {
Auth: {
region: 'eu-central-1',
identityPoolId: 'eu-central-1:xxx',
userPoolId: 'eu-central-1_xxx',
userPoolWebClientId: 'xxxx'
},
API: {
endpoints: [
{
name: "someName,
endpoint: "xxxxx"
}
]
}
}
};
And of course, at the startup of my application I'm configuring amplify like:
...
/** App Environment **/
import { environment } from '../../environments/environment';
...
Amplify.configure(environment.amplify);
...
On my api-gatway I enabled standard CORS
, Authorization
Required and no Token
validation.
I feel like I'm doing everything alright and I don't get what I'm doing wrong.
EDIT:
Authorization
header gets properly set when using API.get(...)
and passing it an header object like:
{
Authorization: 'myToken'
}
More can be read at the following link aws.github.io/aws-amplify
Any Suggestion?
I managed to find out what was causing the problem. The error was caused not by headers nor by code but by the route called. In api-gateway
, you can define resources and methods.
I had an api-gateway
structure like:
/
----testResource/
----/{id}
---- GET
And I was calling testResource?id=someValue
and it was wrong. The right way to call the same resource by id is testResource/someValue
.
For some reason, the gateway, instead of give me a sensed error, gave me:
{
"message": "Authorization header requires 'Credential' parameter. Authorization header requires 'Signature' parameter. Authorization header requires 'SignedHeaders' parameter. Authorization header requires existence of either a 'X-Amz-Date' or a 'Date' header. Authorization=xxxxx"
}
And I tought it was caused by headers in general. For those struggling with the same problem:
AWS_IAM
Authorization but one coming from your cognito user pool
jwt
and pass it to all your API
requests like I've shown in the code above.