How to setup NGINX location authentication with an AWS Cognito hosted UI - amazon-web-services

My goal is to authenticate users to allow access to an NGINX location with AWS Cognito's hosted UI.
I have setup a user pool on Cognito with a hosted UI which works a treat.
I have setup a prototype VueJs app on an NGINX location.
I am struggling to connect the two.
I do not wish to use NGINX Plus.
My location configuration is very basic:
location /AwsCognitoPrototype {
alias /srv/www/AwsCognitoPrototype/;
try_files $uri $uri/ =404;
}
My Cognito UI has Cognito user pool as the only Identity provider. The hosted ui url is something like:
https://auth.example.com/oauth2/authorize?client_id=REDACTED&response_type=code&scope=email+openid+phone&redirect_uri=https%3A%2F%2Fexample.com%2FAwsCognitoPrototype%2F
Which provides an authorization code as the response in the redirect url example.com/AwsCognitoPrototype/?code=50826c34-dabd-4ff6-bc21-98f02dadc544.
After multiple days of experimentation and searching I haven't been able to find any clear examples of how this is supposed to work.
I think what I'm supposed to have in the location definition is an auth_request directive that proxy_passes to the cognito hosted ui endpoint, an error_page directive to catch 401s, etc. But what do you do with the response code? I'm supposed to hit another endpoint on aws cognito to exchange it for a token. There are a couple of other setting in cognito which can send tokens instead but I'm lost there as well.
Haven't even got to introspection yet.
I can't be the only person doing this so either I have missed something really basic or I'm doing it completely wrong!
I have tried finding an example of something similar but have not succeeded. I have not yet got to a point where I have a useful nginx configuration worth trying.
If someone could show how the nginx configuration should be set up in this scenario or point out where conceptually I am wrong it would be greatly appreciated!

Related

Getting Error 400: redirect_uri_mismatch in cognito idp settings

I am following this cognito add social auth to add google auth into one of my app for testing. Completed all steps as listed, but when I am testing that using this
https://<your_user_pool_domain>/login?response_type=code&client_id=<your_client_id>&redirect_uri=https://www.example.com , I am getting an error
Error 400: redirect_uri_mismatch
The redirect URI in the request, https://xxxx-xxxx.auth.ap-south-1.amazoncognito.com/oauth2/idpresponse, does not match the ones authorized for the OAuth client. To update the authorized redirect URIs, visit:
initially the redirect uri and callback url in cognito app client settings were different but i changed those, also I tried changing my redirect url to simple https://google.com, but still not working. I did some research regarding the same, found out that it might take some time to reflect the changes in google oauth setings, its been 2 hrs since I have changed the same, should I wait or is there some other work around this.
Also, I setup facebook login following same doc, it is working fine.
please help!
In my experience this mismatch refers to the difference between your constructed URL and the setting in Cognito Pool. In the pool config, the redirect_uri is called Callback URL. Make sure those two have the same URL.
You can set it in Cognito UI here: App Integration > App Client Settings > Sign in and sign out URLs > Callback URL(s)
or you can specify the URL(s) in your code if you are using CDK.
new cognito.UserPoolClient({
oAuth: {
callbackUrls: ['https://www.example.com', '<url2>'],
}
...
}
Finally I got the solution, redirect url in google auth credentials needs to be your **domainName+/oauth2/idpresponse** .
its has something to do with your uri, whether in google cloud or cognito ,double check if the uri entered is a match

Setting up OIDC for a backend API + frontend SPA

I’ve got a project using a Django backend, with Django Rest Framework to serve an API, and a Vue.js frontend SPA to consume the API. I’m running into some kind of CORS issue during authentication.
I’ve been using mozilla-django-oidc to implement the Authorization Code flow with Okta. This works fine pretty much out of the box, and if I navigate to the API in my browser, I can login to Okta and I get a Django session. I’ve also enabled SessionAuthentication for DRF, which allows the same session cookies generated by Django to be accessible by the SPA (both SPA and API are on the same domain), provided I login first directly through the API. This all works fine until the id token expires. In Django, when the id token expires, I get a redirect to https://example.okta.com/oauth2/v1/authorize?..., the Authorization Code flow completes and I get sent on through to the originally requested page. Where things fail is in an ajax request from the SPA to the API with an expired id token. I get the same redirect, but this time it fails due to CORS.
Access to XMLHttpRequest at 'https://example.okta.com/oauth2/v1/authorize?response_type=code&client_id=X&redirect_uri=http%3A%2F%2F127.0.0.1%3A8000%2Foidc%2Fcallback%2F&state=X&scope=openid+email+profile&prompt=none&nonce=X' (redirected from 'http://127.0.0.1:8080/api/X') from origin 'http://127.0.0.1:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I’ve tried to identify why it’s failing.
On local development, I’m running my API on 127.0.0.1:8000 and my SPA on 127.0.0.1:8080, so clearly the origins don’t match. I have Vue setup with a proxy so it looks like requests are coming from 8080, but the redirect_uri in the request to Okta is still using 8000.
When I deploy to a test server, I’m using docker containers for the API and SPA and a reverse proxy to route requests and also for SSL. In this case, the API and SPA have the same origin (I think). Yet I still get the same error message.
Access to XMLHttpRequest at 'https://example.okta.com/oauth2/v1/authorize?response_type=code&client_id=X&redirect_uri=http%3A%2F%2Fexample.com%2Foidc%2Fcallback%2F&state=X&scope=openid+email+profile&prompt=none&nonce=X' (redirected from 'https://example.com/api/X') from origin 'https://example.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
If you notice, the redirect_uri is http, not https. I suspect that is why this is failing. Though I’m not entirely confident because if I navigate my browser to the API, I am on https, but the redirect_uri is still http, and it still successfully authenticates.
Any insight would be really helpful.
What am I doing wrong or missing here?
Am I approaching the authentication flow all wrong for an API+SPA app? Should I do authentication on the SPA instead? How does the API then know who’s logged in?
Edit: I have already tried adding the origins to the Security > API > Trusted Origins section in Okta configuration. No dice.
https://developer.okta.com/docs/guides/enable-cors/overview/
In Okta, CORS allows JavaScript hosted on your websites to make a request using XMLHttpRequest to the Okta API with the Okta session cookie. Every website origin must be explicitly permitted as a Trusted Origin.
So configure your Trusted Origins properly in the Okta client configuration.
Are you making an AJAX call to /authorize ? That could be the reason for the error.
As mentioned here, when making requests to the /authorize endpoint, the browser (user agent) should be redirected to the endpoint. You can't use AJAX with this endpoint.

Amazon load balancer with cognito returning 401 after sign in

We have an Amazon Load Balancer sitting in front of our application with Cognito as our IdP. We can get to the login page. After the user logs in, they get a "401 Unauthorized" page with the url:
https://xxxxx.com/oauth2/idpresponse?code=xxxx&state=xxxx
What could be some reasons why we're getting this error? Amazon seems to have very light docs around this [0] & [1]. We've already made sure all the oauth2 endpoints are correct (oauth2/token, oauth2/authorize, etc). Not sure where else to look.
Our setup roughly looks like this: https://www.exampleloadbalancer.com/auth_detail.html
[0] https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-troubleshooting.html#http-401-issues
[1] https://aws.amazon.com/premiumsupport/knowledge-center/elb-configure-authentication-alb/
[2] https://docs.aws.amazon.com/elasticloadbalancing/latest/application/listener-authenticate-users.html
Answering my own question.
Turns out the user facing the 401's was using a proxy in their network. That proxy was blocking my website for whatever reason (aka in the end, this had nothing to do with cognito).

Test Cognito results locally?

AWS Cognito doesn't accept localhost as signin url. My app is hosted on S3 and behind a CloudFrnot distribution, so we can get https url. I'm using amazon-cognito-auth-js to do authentication on my app. Even if I run my app locally, after authentication, it will redirect me to my cloudfront url, and I need to check logs from Chrome developer tool. So for any change / test, I need to build my app, and upload it on S3, use a new inognito sesison on my browser. I'm wondering is there an easier way to do local development with Cognito? Is there any way to redirect Cognito to localhost and do local test there? Any other idea is welcomed.
Found the answer: you can add http://localhost:3000 as callback url (sign in) into your User Pool App client. You can either create a new app client for this purpose, or add a new callback url (comma separated) to existing app; each user pool client app can have multiple call back urls.
You can use localhost to test out cognito. The problem is that cognito doesn't allow HTTP. If you install an IIS certificate on you computer to use HTTPS on your machine, you will be able to use that as callback url. A tutorial for doing this is here

Nginx, SPA & Sphinx Doco Authentication

I have an SPA app which uses Azure AD for authentication. It's working well and now I've added some user doco using Sphinx.
I've configured Nginx so the doco is available via /app/doco. This works well, however now I would like to also secure it so only Azure AD authenticated users can access the doco. To do this I have made use of the auth_request (http://nginx.org/en/docs/http/ngx_http_auth_request_module.html) module. This works if I am using standard Django authentication but when I use Azure AD authentication it isn't working as the request does not have the users token included etc.
The way I understand the auth_request module to work is:
User attempts to access /app/doco (which includes the users token)
Nginx is configured to check if the user is authenticated by going to /app/auth_check (custom Django view) which returns either 200 or 404
If 200, user is given access to /app/doco
It feels like that above approach is flawed, trying to hit a square peg through a round hole? Will something like the above work or is there another tool/approach that better fits?
From the Azure side I can't really speak to this since we do not have official documentation for this, but based off of what I have seen on Nginx you should be able to use JWTs and conditional access to achieve this.
Looks like you may need to add JWT validation to your NGINX configuration:
auth_jwt "Closed site";
auth_jwt_key_file /etc/nginx/azure.jwk;
Have you seen this guide already?