Last active
January 6, 2019 11:33
-
-
Save ckimrie/96e4992036c559c1f046476d3fc16a7e to your computer and use it in GitHub Desktop.
How to use AWS Cognito to sign an http request to a custom AWS Api Gateway using IAMs Authorization.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//---- Angular 2 Http Service Example ---- | |
import {Injectable} from "@angular/core"; | |
import {Http, Headers} from "@angular/http"; | |
const AWS = require("aws-sdk"); | |
@Injectable() | |
export class ApiGatewayService { | |
constructor(private http:Http){ | |
let creds = new AWS.CognitoIdentityCredentials({ | |
IdentityPoolId: "eu-west-1:xxx-xxxx-xxxxxxxx" | |
}); | |
AWS.config.update({ | |
region: 'eu-west-1', | |
credentials: creds | |
}); | |
AWS.config.credentials.get((err) => { | |
if(err) throw err; | |
let httpRequest = new AWS.HttpRequest("https://xxxxx.execute-api.eu-west-1.amazonaws.com/v1/my/api", "eu-west-1"); | |
httpRequest.method = "POST"; | |
httpRequest.headers.host = "xxxxx.execute-api.eu-west-1.amazonaws.com"; | |
httpRequest.headers['Content-Type'] = "application/json"; | |
httpRequest.body = JSON.stringify({ | |
data: { | |
username: 'foo', | |
password: 'bar', | |
applicationName: 'biz', | |
} | |
}); | |
let v4signer = new AWS.Signers.V4(httpRequest, "execute-api", true); | |
v4signer.addAuthorization(AWS.config.credentials, AWS.util.date.getDate()); | |
//Create a headers object from the AWS signed request | |
let headers = new Headers(); | |
for(let key of Object.keys(httpRequest.headers)){ | |
headers.set(key, httpRequest.headers[key]); | |
} | |
headers.delete('host'); //Browser throws a warning if attempting to set host header | |
this.http.post(httpRequest.endpoint.href, httpRequest.body, { | |
method: httpRequest.method, | |
search: httpRequest.endpoint.search, | |
headers: headers | |
}).subscribe((data)=>{ | |
console.log(data); //Success | |
}); | |
}) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//---- Complete code example to sign AWS Http request ---- | |
//Configure AWS | |
AWS.config.update({ | |
region: 'eu-west-1', | |
//CognitoIdentityCredentials only needed if using Cognito. Use credentials specific to your usecase | |
credentials: new AWS.CognitoIdentityCredentials({ | |
IdentityPoolId: "eu-west-1:xxxx-xxxxx-xxxxxxx" | |
}); | |
}); | |
//Create an HttpRequest representation of your request (this wont actually _DO_ the request) | |
var httpRequest = new AWS.HttpRequest("https://xxxxxxx.execute-api.eu-west-1.amazonaws.com/uri/to/method", "eu-west-1"); | |
//REQUIRED | |
//Host & content type headers must be set | |
httpRequest.headers.host = "xxxxxxx.execute-api.eu-west-1.amazonaws.com"; //Host of the API being called | |
httpRequest.headers['Content-Type'] = "application/json"; | |
//OPTIONAL | |
httpRequest.method = "GET"; //Default is POST | |
httpRequest.headers['x-biz'] = 'baz'; //Additional headers | |
httpRequest.body = JSON.stringify({foo:'bar'}); //Body must be a string if being used | |
//Instruct cognito credentials to get access, secret and session keys (only needs to be done once on page load) | |
AWS.config.credentials.get(function(err){ | |
//Sign the request with the newly fetched credentials. All IAM Authorised API Gateway requests use the V4 signer | |
var v4signer = new AWS.Signers.V4(httpRequest, "execute-api", true); | |
v4signer.addAuthorization(AWS.config.credentials, AWS.util.date.getDate()); | |
//The httpRequest has now been signed with the credentials. You can pick it apart and use your own AJAX/Fetch library | |
//The AWS.HttpRequest itself isn't able to make the request on its own | |
console.log(httpRequest.headers) // { authorization: 'AWS4-HMAC-SHA256 Credential=ASIA...', x-amz-security-token:'AgoGb...', ...} | |
console.log(httpRequest.method) // GET | |
console.log(httpRequest.endpoint.href) // https://xxxxxxx.execute-api.eu-west-1.amazonaws.com/uri/to/method | |
console.log(httpRequest.body) | |
}); |
Hello Christopher,
Thanks for sharing this solution, however this does not work any more, because the AWS.Signers
class is not public in the current version of the SDK. See aws/aws-sdk-js#1247. This may be the solution: https://github.com/mhart/aws4.
Hope this helps,
György
Is this code safe? It has username and password in the client-side script??
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here's an example of how to use the above to sign a request with the Angular 2 Http library: