Reputation: 3975
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?
Upvotes: 3
Views: 2274
Reputation: 3975
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.Upvotes: 0
Reputation:
I don't get your issue so I will rely on the title of your question.
If a header is missing, it's because Angular simplifies the headers before giving your the response.
If you want to get the header and put it in your request, you will have to expose it.
This is done with the Access Control Expose Headers header.
By default, Angular only handle a couple of headers and erase the other ones. You probably didn't get your token because it was in a non exposed header.
Upvotes: 1