AWS API Gateway Authentication with OneLogin - amazon-web-services

I've been exploring OneLogin and I think I have a basic understanding of how to use it; I was successful at configuring the Node+Passport sample application to authenticate with OneLogin and I understand the code.
I want to try it with AWS API Gateway. I've got an API already defined in AWS. On a high level I know I need to configure an Authorizer in AWS for OneLogin and that there is going to be some bit of information that I will need to pass in a header when I make my calls to the AWS Api Gateway (I assume a Bearer token that I get from authenticating with OneLogin before I interact with AWS, but I don't know).
Can someone give me a description of what I need to do? The most recent question that I see here on the topic was posted in 2016 back when the answer was "You can't do that." That answer has changed in the past 4 years. The OneLogin documentation says it can be done, but I have found not information on how to do it.

GENERAL PATTERN
The role of an authorizer function is to perform the following actions:
Validate access token
Optionally collect additional claims
Cache the claims for subsequent requests with the same token
Provide claims to business logic
In fact this is a general pattern that can be used anywhere, as referenced in my blog post.
TOKEN VALIDATION
I would use the One Login Introspection Endpoint.
Some NodeJS code of mine that calls an introspection endpoint is here.
AWS SPECIFICS
Since you are using OneLogin you will need to write some custom code. Your lambda authorizer will need to do standard OAuth 2.0 work, then return an AWS policy document. Some resources of mine may help you to understand how this works:
Lambda Authorizer Blog Post
Associated NodeJS Code
PAIN POINTS
The AWS plumbing is a bit painful, and it is possible you are using some different technology choices to me - I am using the Serverless Framework.
Hopefully though, this gives you something to run locally and compare against. Happy to answer any follow up questions ...

Related

google api key gets 401

I am trying to call some endpoints on google cloud build but I just get 401 and I am wondering how to fix this? In the end, I want to curl but if the website is not working, there is truly something wrong! Here is the picture
Only a group of API services/products on Google Cloud Platform support API keys without more authentication methods (OAuth). You can find these specific services here. In the same page that you posted, if you go down on the documentation there should be a "Authorization Scopes" section listing the required OAuth scopes that the API requires, if so, it means OAuth is needed in order to use the service.
I look at the Cloud Build Rest Api Doc and indeed I can see OAuth is required, in addition to not being listed here. You need to implement OAuth for this specific Service (Cloud Build API).

AWS Cognito Hosted UI -- How to use the returned JWT token?

I am using Amazon Cognito and its hosted UI to help create a web application. I am able to use to log in using the hosted UI and the redirect link successfully points me to where I want it to go. I also recieve a correctly formatted JWT token on redirect.
I've also successfully parsed that JWT token into a JS object and am able to verify its validity. With the correct username, expiration time, issue time, etc., etc.
The problem I'm having now is that I simply don't know where to go from here. Is the fact that I have that JWT enough to continue on and assume that the user is valid? If I want to be able to persist the user across different webpages on the site, is it safe to store the JWT -- or, at least, parts of it -- in session storage and act as if that is valid user?
If not, then what am I supposed to do next with the JWT? I have looked through many of the various articles on using the JWT with Cognito and they all seem to be about decoding the JWT, but not about what I'm supposed to do with the JWT once I have it decoded.
For context, all I am really trying to get from the JWT is the correct user name, I am planning on storing a lot of other important user details elsewhere.
I'm sorry if there is something very obvious I'm missing about where to go next, but I'm very new to all this AWS stuff and a lot the of documentation is confusing, and not beginner friendly. Thank you for your time, any help at all is greatly appreciated.
EDIT: I wanted to include that I am writing the log in / verification / redirect code on vanilla, client-side javascript. I am using the standard aws SDK, the aws-cognito SDK, and the amazon-cognito-identity SDK. My imports look like this:
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.686.0.min.js"</script>
<script src="../../aws-cognito/dist/amazon-cognito-auth.min.js" type="text/javascript"></script>
<script src="../../amazon-cognito-identity-js/dist/amazon-cognito-identity.min.js"></script>
my advise for you would be to look into the AWS Client Side SDK which handle the storing, refreshing and other nice functionality for you.
https://docs.amplify.aws/start/q/integration/js - Main Client side SDK.
https://github.com/amazon-archives/amazon-cognito-auth-js - older SDK used for Cognito Oauth endpoints/ Hosted UI.
Both SDK's will store the result from your HostedUI authentication is local storage in the browser. There you can check if the tokens are valid and even access them if you require to send them to an authorized resource server.
This of course can all be implemented without the use of those SDK's but they help and can give you poinnters. Additionally, the AWS SDK and Cognito identity SDK do not have any functionality that will help you integrate with the HostedUI and Oauth endpoints. That can be done using the SDK's provided above.

How to use AWS SDK for request signing

I'm trying to invoke an api request (service: execute-api) and a Signature v4 is required. I've been going through the documentation and I see clearly this:
Alternatively, you can use the AWS CLI or one of the AWS SDKs to
handle request signing for you.
I don't own the API and originally just thought I could use CURL but obviously IAM is configured. I'm wondering what the best way of making this request signed is?
Note:
Looks like there is an AWS4Signer class that may be what I'm looking for to generate the signature non-manually
I'm sorry, but from your question it's not clear whether you're just experimenting with the API or if you want to write a client that calls it (as in production code).
If you're just testing, you can use Postman to call the API (it supports SigV4). Details here.
If you are writing a client, the way to go is generating the SDK from API gateway, as noted in the comments. Should that not be possible, the next best option is to use one of the language-specific SDK signers to generate the SigV4 signature. AWS4Signer, like you said, is the way to go. It should be straightforward to integrate with it, but if you can share more details of your specific use case (platform, language, where do you get the AWS credentials from, etc), people can give you a better answer.
Last, if you want to generate the signature yourself, here's how the canonical generation of signatures work.

API Key enabled, but requests without key still running

In my API Gateway console, I did the following:
Created an API key
Associated the key with a deployed API stage
Checked the key's "Enabled" checkbox
For each method of each resource of my API, required the API key for authentication
I expected curl https://my-api-gateway-url/my-resource to 403, since I didn't include the x-api-key header, but it was a 200 instead. My Lambda function behind API Gateway ended up running when it shouldn't have run without the API key.
How can I ensure the key is required to authenticate all requests?
EDIT: I was following the documentation here: http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-api-keys.html
Just answered my own question. Posting my answer here as I know I'm not the only one wondering about this, like this person.
The answer is to redeploy your API. Although redeploying sounds obvious, the docs completely skip the vital last step, so it's easy to overlook.

Interaction with the AWS API?

I've gotten the necessary access key/signature from my client and I can interact with the API through the Ruby SDK right now. Thing is, the Ruby SDK doesn't have any kind of high-level API methods to request a spot instance. So, I need to do this manually via raw REST API requests.
Basically, the authentication information that I am using is correct (as it works via the Ruby SDK), but I can't get raw requests to work... I either get back the spot request wizard webpage as the response, or an error: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
Here's the URL I'm using:
https://ec2.amazonaws.com/?Action=RequestSpotInstances
&SpotPrice.1=0.05
&AvailabilityZoneGroup.1=us-east-1c
&LaunchSpecification.ImageId.1=THE_AMI_ID
&LaunchSpecification.KeyName.1=THE_KEYPAIR
&LaunchSpecification.InstanceType.1=m1.medium
&AWSAccessKeyId=THE_ACCESS_KEY
&Signature=THE_ACCESS_SIGNATURE
&Version=>2013-10-01
&Expires=>THE_EXPIRATION_TIME_36000_SECONDS_LATER_THAN_NOW
&SignatureVersion=2
&SignatureMethod=HmacSHA256
Any ideas on why this won't work? I've tried exploring the Ruby SDK code to see how they are doing it, but it's so complex, I can't figure out where this action actually takes place. Thanks!
How do you calculate signature? First at all check that you use correct signing process version. AWS api actually supports versions v2 and v4. Some aws resources supports both versions, some just v2 or v4. Base on this I would recommend to do following:
Check what version of the signing did you implement. More on versions:
http://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html
Check is your implementation match with algorithm described here: http://docs.aws.amazon.com/general/latest/gr/signature-version-2.html