AWS AppSync with Firebase as OpenID Connect provider - amazon-web-services

I would like to use firebase auth to secure my AWS AppSync graphql api, as opposed to something like Cognito. There are several reasons behind this like pricing and us already using some other firebase services.
The only viable solution I can see atm is to somehow pass firebase user token to my AppSync graphql api and validate it through OpenID Conneect / OIDC.
I was not able to figure this out nor find any guides on the topic, so wanted to ask here if it is even possible, if so, could any examples be provided or perhaps use-full references?
Here are related fields that need to be provided to AppSync in terms of OpenID connect data https://docs.aws.amazon.com/cdk/api/latest/docs/#aws-cdk_aws-appsync.OpenIdConnectConfig.html
Do these exist for firebase auth?
Update: I was able to find some documentation on firebase token verification https://firebase.google.com/docs/auth/admin/verify-id-tokens#verify_id_tokens_using_a_third-party_jwt_library
I believe following URL is what needs to be used as OpenID url setting in AppSync https://www.googleapis.com/robot/v1/metadata/x509/securetoken#system.gserviceaccount.com
However AppSync documentation states that they append /.well-known/openid-configuration to such url and when I do that to googleapis url above, it throws 404.

AppSync expects an OpenID Connect Provider (OP). More specifically, it wants the OP's issuer; the rest of metadata is retrieved based on that. From AppSync doc:
OPENID_CONNECT Authorization
This authorization type enforces OpenID Connect (OIDC) tokens provided by an OIDC-compliant service.
Your application can leverage users and privileges defined by your
OIDC provider for controlling access.
An Issuer URL is the only required configuration value that you
provide to AWS AppSync (for example, https://auth.example.com). This
URL must be addressable over HTTPS. AWS AppSync appends
/.well-known/openid-configuration to the issuer URL and locates the
OpenID configuration at
https://auth.example.com/.well-known/openid-configuration per the
OpenID Connect Discovery specification
Firebase is (mostly) a middleware. Even though you could have a user account be residing in Firebase, a more typical use case is to plug in some provider such as Google or Microsoft into Firebase. You could then use Firebase APIs to perform various operations without having to know the details of the underlying provider.
Whether acting as middleware or as an identity store with users in Firebase, it's unclear if Firebase is an OIDC-compliant provider. OpenID publishes OIDC conformance tests as well as entities that have been certified. The only Google entity on the latter list is a "Google Federated Identity". Certification aside, Firebase does issue a signed JWT that according to them is morally equivalent to id_token in OIDC:
ID token verification
If your Firebase client app communicates with
your backend server, you might need to identify the currently
signed-in user on your server so you can perform server-side logic on
their behalf. You can do this securely by using ID tokens, which are
created by Firebase when a user signs into an Firebase app.
ID tokens
conform to the OpenID Connect spec and contain data to identify a
user, as well as some other profile and authentication related
information. You can send, verify, and inspect these tokens from your
own backends. This allows you to securely identify the currently
signed in user and authorize them into your own backend resources.
If you create a Firebase project, then authenticate via that and examine the issued token, you'll see the iss (Issuer) key in the token payload. It has a value of https://securetoken.google.com/<Firebase projectId> and that's the URL needed by AppSync.
You can confirm that OIDC metadata is available by concatenating /.well-known/openid-configuration with https://securetoken.google.com/<Firebase projectId> and doing a GET on the resulting URL. The expected response should look like this:
{
"issuer": "https://securetoken.google.com/<Firebase project id>",
"jwks_uri": "https://www.googleapis.com/service_accounts/v1/jwk/securetoken#system.gserviceaccount.com",
"response_types_supported": [
"id_token"
],
"subject_types_supported": [
"public"
],
"id_token_signing_alg_values_supported": [
"RS256"
]
}

Related

Is there any OpenID Connect Identity Provider that can delegate autentication to other OpenID Connect IdPs?

I'm facing the following scenario:
There are several companies each one with its own OpenID Connect Identity Provider (IdP) which federates users from their respetive LDAP servers. These providers are used to perform SSO in the context of each company.
There's a requirement to create an application that offers a common login for all the users of those companies.
The idea is to provision or use an existing cloud solution (AWS Cognito, Google Cloud Identity, etc., ...) that offers a shared login screen but delegates/federates the actual login to each of the company IdPs.
Are there any solutions that allows this?
Could you point at any documentation/guide to implement it?
This is just standard OAuth and OpenID Connect behaviour, with these 3 roles:
Application, uses OIDC to redirect to ...
An Authorization Server, which you own, and which redirects to ...
An Identity Provider
So you need a standards based authorization server and to configure your app as an OAuth Client. Then include the openid scope so that OpenID Connect is used. SAML based identity providers can also be supported in this flow, even though your app only uses OIDC.
The way to manage this with best usability, is for the authorization server to present a usernane authenticator, which captures a user identifier first, such as an email. It then runs some custom logic, such as a user lookup, to determine which IDP to route the user to. The user then authenticates at the IDP.
After authentication, the IDP issues tokens to the authorization server, which validates them, then issues its own tokens to the application. In particular the app gets an access token whose scopes and claims you can control. Your app can then send these to your APIs, which can authorize access to business data correctly.
Aim for behaviour similar to that above, or adjust it based on your preferences. Then trial it, eg with a cloud or Docker based authorization server, and ensure that you select one with sufficient extensibility to meet your requirements.
Note also that Stack Overflow answers should not recommend particular vendors, so I have not done so.
There is a solution called cloudpods using which you can manage both on-prem and public cloud resources. Cloudpods supports integration with multiple cloud providers like aws, GCP, azure, alibaba and etc.,
Is there any OpenID Connect Identity Provider that can delegate autentication to other OpenID Connect IdPs?
Yes. https://github.com/apereo/cas is one. You can set it up as an OIDC identity provider and have it then delegate to as many OIDC Identity providers as you want.

Usage of ID tokens and Access tokens, with external Authentication, AWS backend and graphql language

I am currently working on building a mobile app which will require the users be authenticated, and have them specific privileges on what they can do (for example, a logged in user will only be able to manage some of their data held in the backend database).
I think I do understand the differences between ID token (user identity) and Access token (for authorizing between the mobile phone client and the back-end), but I am not sure what I intend to do conforms to the best practices regarding authentication and authorization.
Let me summarize what I am planning to do:
front end will be a Flutter/Dart mobile app
authentication will be done through Google Firebase Authentication service
my back end will be hosted in AWS:
API Gateway will serve a unique graphQL endpoint
API Gateway has an associated Lambda authorizer function which processes requests prior to the actual "application" Lambda functions
"application" Lambda function serves GraphQL requests (using python ariadne library), including authorization business logic
Database is a managed PostGreSQL inside AWS
The authentication / authorization workflow is as follow:
Not all of this has been implemented yet, but on the paper I think it could work.
However, it goes against several good practices regarding token usage:
the ID token is sent along an API call which is advised against (see this nice auth0 blog post)
I make no usage of access token between the front end and the back-end (could the AWS policy generated at step 5 fullfill this role?)
I do not leverage the audience claims in tokens
Note: as GraphQL exposes a single endpoint, I am not sure of what the content of the access token should be
I am new to Authentication / Authorization and would gladly have some insight regarding the best way to actually make everything work as per best practices, accounting to the following contraints:
authentication is outside of AWS
the APIs are GraphQL

Shopify and AWS Cognito OIDC

I'm trying to use Shopify as an AWS Cognito User Pool "federated identity provider". Ostensibly, it seems to follow the OIDC protocol. However, there seems to be scant information on the format of the ProviderDetails field in the AWS API call, and I can't seem to figure out how to correctly pass the Issuer for Shopify. I've tried to do it through the console as well, but keep getting the message:
Discovery returned no results. Check the issuer and run discovery again or manually add the required fields below.
I suspect that, due to Shopify's multitenancy model, I'll never get a single set of OIDC parameters -- it seems to suggest there is a different URL for each shop.
Is there documentation on either (a) how to set up Shopify as an OIDC provider -- including Issuer, Authorization Endpoint, Token Endpoint, etc. -- or (b) why Shopify does not match the OIDC standard?

OpenID authentication in AWS API gateway

I created an API with AWS API gateway that triggers a lambda function. Now I want to restrict access to this API. I own an OpenID connect identity provider.
I want to require people to authenticate with my OpenID identity provider before accessing the API. What is the best way to do that? Apparently, I need an authorizer for my API. I read a lot of documentation, and from what is mentioned here, it seems that this would be possible with amazon cognito. However, here I can only find a way to use cognito user pools, while I want to use a cognito identity pool.
I want the typical authentication scenario, e.g. user calls the api, is redirected to my openid id provider, logs in, and can then access my api (which delivers html so all of this will be taking place in a web browser).
Is this actually possible with cognito, or do I need to write a custom lambda authorizer? If so, is there any documentation on writing an authorizer lambda that uses openid, prefereably in .NET?
You are mixing Authentication and Authorization.
Federated Identity Provider to Cognito:
You can use OpenID Federated Identity provider for Authentication.
Below documentation provides on how to configure it,
https://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html
Once authenticated you can create a signed URL to protect your assets for the URL which you want to allow to.
Creating Signed URLs:
Below documentation providers on how to created signed URL's using C#.
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CreateSignatureInCSharp.html
Custom Authorizer:
Following commit on github shows an example implementation of C# custom authorizer.
https://github.com/awslabs/aws-apigateway-lambda-authorizer-blueprints/pull/13/commits/79d75fb7c5ee4f29fa06fd2ec28c704224cf8a7a
Hope it helps.

Using Login with Paypal and using OpenID with AWS Cognito

I am trying to use the OpenID framework supported by Paypal to tie the credentials in with the AWS Cognito service.
If I compare the configuration from Salesforce
https://login.salesforce.com/.well-known/openid-configuration
to the configuration at Paypal
https://www.paypal.com/.well-known/openid-configuration
the Paypal configuration is missing the jwks_uri element which is a REQUIRED element of the OpenID Provider metadata per OIDC specification and AWS uses the keys at that URI to verify the id tokens.
Is there a different url I should be using for login with Paypal to work with OpenID?
Is there any other way to get Login with Paypal to work with the AWS Cognito service with works well with other OpenID providers?
Paypal is not OpenID Connect compliant:
as you mention the Discovery document lacks required entries, but:
the ID token is signed with a symmetric key this means that no JWKS URI is actually needed since no public/private keys are used (and publishing the symmetric key on that URI defeats the purpose)
but apparently it is not the client secret that is used to sign the ID token as verification with that fails
there's no sub claim in the ID token
the exp claim is not set to an absolute timestamp but a relative timeout
Since Amazon Cognito works with OpenID Connect compliant providers, Paypal is not going to work.