{"id":21354881,"url":"https://github.com/salrashid123/awscompat","last_synced_at":"2025-07-12T22:32:17.394Z","repository":{"id":91309741,"uuid":"268312480","full_name":"salrashid123/awscompat","owner":"salrashid123","description":"Google and Firebase OIDC tokens for AWS STS","archived":false,"fork":false,"pushed_at":"2024-10-28T16:53:18.000Z","size":407,"stargazers_count":3,"open_issues_count":3,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-28T17:52:13.156Z","etag":null,"topics":["aws","aws-sts","google-cloud-platform"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/salrashid123.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-31T15:52:36.000Z","updated_at":"2024-10-28T16:53:02.000Z","dependencies_parsed_at":"2023-10-02T12:27:05.562Z","dependency_job_id":null,"html_url":"https://github.com/salrashid123/awscompat","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fawscompat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fawscompat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fawscompat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fawscompat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/salrashid123","download_url":"https://codeload.github.com/salrashid123/awscompat/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225839601,"owners_count":17532308,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","aws-sts","google-cloud-platform"],"created_at":"2024-11-22T04:14:48.380Z","updated_at":"2024-11-22T04:14:48.979Z","avatar_url":"https://github.com/salrashid123.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"### Exchange Google and Firebase OIDC tokens for AWS STS\n\n\nSimple [AWS Credential Provider](https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials/) that uses [Google OIDC tokens](https://github.com/salrashid123/google_id_token).\n\nEssentially, this will allow you to use a google `id_token` for AWS STS `session_token` and then access an aws resource that you've configured an Access Policy for the google identity.  This repo creates an `AWS Credential` derived from a `Google Credential` with the intent of using it for AWS's [IAM Role using External Identities](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html).\n\n[Firebase](https://firebase.google.com/) and [Google Cloud Identity Platform](https://cloud.google.com/identity-platform/docs) based `id_tokens` can also be uses for this exchange but is not wrapped into this library (critically since there isn't a golang client library to acquire them).  \n\n\u003e\u003e *NOTE*: the code in this repo is not supported by google.\n\n### Implementations\n\n* [golang](#golang)\n* [java](#java)\n* [python](#python)\n* [dotnet](#dotnet)\n* [nodejs](#nodejs)\n\n### References\n\n#### AWS\n- [AWS Identity Providers and Federation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers.html)\n- [AWS WebIdentityRoleProvider](https://docs.aws.amazon.com/sdk-for-go/api/aws/credentials/stscreds/#WebIdentityRoleProvider)\n- [AWS AssumeRoleWithWebIdentity](https://docs.aws.amazon.com/sdk-for-go/api/service/sts/#STS.AssumeRoleWithWebIdentity)\n- [aws.credential.Provider](https://godoc.org/github.com/aws/aws-sdk-go/aws/credentials#Provider)\n\n#### Google\n- [Authenticating using Google OpenID Connect Tokens](https://github.com/salrashid123/google_id_token)\n- [Securely Access AWS Services from Google Kubernetes Engine (GKE)](https://blog.doit-intl.com/securely-access-aws-from-gke-dba1c6dbccba)\n- [https://accounts.google.com/.well-known/openid-configuration](https://accounts.google.com/.well-known/openid-configuration)\n\n\n#### Firebase\n- [Firebase Storage and Authorization Rules engine 'helloworld'](https://blog.salrashid.me/posts/firebase_storage_rules/)\n\n\n### Google OIDC\n\nAWS already supports Google OIDC endpoint out of the box as a provider so the setup is relatively simple: just define an AWS IAM policy that includes google and restrict it with a `Condition` that allows specific external identities as shown below:\n\n\n- The following definition refers to Role: `arn:aws:iam::291738886548:role/s3webreaderrole`\n\n```json\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Principal\": {\n        \"Federated\": \"accounts.google.com\"\n      },\n      \"Action\": \"sts:AssumeRoleWithWebIdentity\",\n      \"Condition\": {\n        \"StringEquals\": {\n          \"accounts.google.com:sub\": \"100147106996764479085\"\n        }\n      }\n    }\n  ]\n}\n```\n\n![images/s3_trust.png](images/s3_trust.png)\n\n\nTo do this by hand, first acquire an ID token (in this case through `gcloud` cli and service account):\n\n```bash\n$ gcloud auth activate-service-account --key-file=/path/to/gcp_service_account.json\n\n$ export TOKEN=`gcloud auth print-identity-token --audiences=https://foo.bar`\n```\n\nDecode the token using the JWT decoder/debugger at [jwt.io](jwt.io)\n\nThe token will show the unique `sub` field that identifies the service account:\n\n```json\n{\n  \"aud\": \"https://foo.bar\",\n  \"azp\": \"svc-2-429@mineral-minutia-820.iam.gserviceaccount.com\",\n  \"email\": \"svc-2-429@mineral-minutia-820.iam.gserviceaccount.com\",\n  \"email_verified\": true,\n  \"exp\": 1590898991,\n  \"iat\": 1590895391,\n  \"iss\": \"https://accounts.google.com\",\n  \"sub\": \"100147106996764479085\"\n}\n```\n\nOr using gcloud cli again:\n\n```bash\n$ gcloud iam service-accounts describe svc-2-429@mineral-minutia-820.iam.gserviceaccount.com\n    displayName: Service Account A\n    email: svc-2-429@mineral-minutia-820.iam.gserviceaccount.com\n    etag: MDEwMjE5MjA=\n    name: projects/mineral-minutia-820/serviceAccounts/svc-2-429@mineral-minutia-820.iam.gserviceaccount.com\n    oauth2ClientId: '100147106996764479085'\n    projectId: mineral-minutia-820\n    uniqueId: '100147106996764479085'\n```\n\nUse this `uniqueId` value in the AWS IAM Role policy as shown above.\n\n\u003e\u003e *Note*:  I tried to specify an audience value (`\"accounts.google.com:aud\": \"https://someaud\"`) within the AWS policy but that didn't seem to work)\nWhich means while the `audience` (aud) value is specified in some of the samples here (eg `\"https://sts.amazonaws.com/` or `https://foo.bar`) can be anything since its not even currently used in the AWS condition policy)\n\n\nExport the token and invoke the STS endpoint using the `RoleArn=` value defined earlier\n\n```bash\nexport TOKEN=eyJhbGciOiJSUzI1...\n\n$ curl -s \"https://sts.amazonaws.com/?Action=AssumeRoleWithWebIdentity\u0026DurationSeconds=3600\u0026RoleSessionName=app1\u0026RoleArn=arn:aws:iam::291738886548:role/s3webreaderrole\u0026WebIdentityToken=$TOKEN\u0026Version=2011-06-15\u0026alt=json\"\n```\n\nYou should see AWS `Credential` object in the response\n```xml\n\u003cAssumeRoleWithWebIdentityResponse xmlns=\"https://sts.amazonaws.com/doc/2011-06-15/\"\u003e\n  \u003cAssumeRoleWithWebIdentityResult\u003e\n    \u003cAudience\u003esvc-2-429@mineral-minutia-820.iam.gserviceaccount.com\u003c/Audience\u003e\n    \u003cAssumedRoleUser\u003e\n      \u003cAssumedRoleId\u003eAROAUH3H6EGKKRVTHVAVB:app1\u003c/AssumedRoleId\u003e\n      \u003cArn\u003earn:aws:sts::291738886548:assumed-role/s3webreaderrole/app1\u003c/Arn\u003e\n    \u003c/AssumedRoleUser\u003e\n    \u003cProvider\u003eaccounts.google.com\u003c/Provider\u003e\n    \u003cCredentials\u003e\n      \u003cAccessKeyId\u003eASIAUH3H6EGKPI...\u003c/AccessKeyId\u003e\n      \u003cSecretAccessKey\u003eEM3Zu4RlDOKGkFPJpceemRqEzfazLk...\u003c/SecretAccessKey\u003e\n      \u003cSessionToken\u003eFwoGZXIvYXd...\u003c/SessionToken\u003e\n      \u003cExpiration\u003e2020-05-31T04:23:39Z\u003c/Expiration\u003e\n    \u003c/Credentials\u003e\n    \u003cSubjectFromWebIdentityToken\u003e100147106996764479085\u003c/SubjectFromWebIdentityToken\u003e\n  \u003c/AssumeRoleWithWebIdentityResult\u003e\n  \u003cResponseMetadata\u003e\n    \u003cRequestId\u003e38dd604d-6ce2-45b3-8e6f-1165ae0e24a1\u003c/RequestId\u003e\n  \u003c/ResponseMetadata\u003e\n\u003c/AssumeRoleWithWebIdentityResponse\u003e\n```\n\nYou can manually export the `Credential` in an cli (in this case, to access `s3`)\n\n```bash\nexport AWS_ACCESS_KEY_ID=ASIAUH3H6EGKIL...\nexport AWS_SECRET_ACCESS_KEY=+nDF8O2yLDH13ug...\nexport AWS_SESSION_TOKEN=FwoGZXIvYXd...\n\n$ aws s3 ls mineral-minutia --region us-east-2\n\n    2020-05-29 23:04:07        213 main.py\n\n```\n\nTo make this easier, the golang library contained in this repo wraps these steps and provides an AWS `Credential` object for you:\n\n\n### Usage\n\nThere are several ways to exchange GCP credentials for AWS:\n\nYou can either delegate the task to get credentials to an external AWS `ProcessCredential` binary or perform the exchange in code as shown in this repo.\n\n#### Process Credentials\n\nIn the `ProcessCredential` approach, AWS's client library and CLI will automatically invoke whatever binary is specified in aws's config file.  That binary will acquire a Google IDToken and then exchange it for a `WebIdentityToken` SessionToken from the AWS STS server.  Finally, the binary will emit the tokens to stdout in a specific format that AWS expects.  \n\nFor more information, see [Sourcing credentials with an external process](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sourcing-external.html) and [AWS Configuration and credential file settings](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html)\n\nTo use the process credential binary here, first\n\n1. Build the binary (or download from \"Releases\" page)\n\n```bash\ngo build  -o gcp-process-credentials main.go\n```\n\n2. Create AWS Config file\n\ncreate a config file under `~/.aws/config` and specify the path to the binary, the ARN role and optionally the path to a specific gcp service account credential.\n```bash\n[default]\ncredential_process = /path/to/gcp-process-credentials  --aws-arn arn:aws:iam::291738886548:role/s3webreaderrole  --gcp-credential-file /path/to/svc.json  --region=us-east-2\n```\nIn the snippet above, i've specified the GCP ServiceAccount Credentials file path.  If you omit that parameter, the binary will use [Google Application Default Credential](https://cloud.google.com/docs/authentication/production) to seek out the appropriate Google Credential Source.   \n\nFor example, if you run the binary on GCP VM, it will use the metadata server to get the id_token.   If you specify the ADC Environment varible `GOOGLE_APPLICATION_CREDENTIALS=/path/to.json`, the binary will use the service account specified there\n\n3. Invoke AWS CLI or SDK library\n\nThen either use the AWS CLI or any SDK client in any language.  The library will invoke the process credential for you and acquire the AWS token.\n\n```bash\n$ aws s3 ls mineral-minutia --region us-east-2\n```\n\nThe example output from the binary is just JSON:\n\n```bash\n\n$ gcp-process-credentials  --aws-arn arn:aws:iam::291738886548:role/s3webreaderrole  --gcp-credential-file /path//to/svc.json  --region=us-east-2 | jq '.'\n{\n  \"Version\": 1,\n  \"AccessKeyId\": \"ASIAUH3H6EGKL7...\",\n  \"SecretAccessKey\": \"YnjWyQFDeeqkRVJQit2uaj+...\",\n  \"SessionToken\": \"FwoGZ...\",\n  \"Expiration\": \"2020-06-05T19:24:57+0000\"\n}\n```\n\n### Language Native\n\nThe other approach is to exchange the GoogleID token for an AWS one using the AWS Language library itself.  This has the advantage of being \"self contained\" in that there is no need for an external binary to get installed on the system.\n\nThe snippet below demonstrate how to do this in various languages.   For golang and java specifically, the exchange is done a custom AWS credential wrapper which has the distinct advantage of being \"managed\" just like any other standard AWS Credential type in that any refresh() that is needed on the underlying credential will be self-managed.\n\nAt the moment (5/5/20), I havne't been able to figure out how to do this with python..\n\n#### Golang\n\nTo use the managed credential in golang, import `\"github.com/salrashid123/awscompat\"` as shown below\n\n```golang\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"log\"\n\n\t\"github.com/aws/aws-sdk-go-v2/aws\"\n\t\"github.com/aws/aws-sdk-go-v2/config\"\n\t\"github.com/aws/aws-sdk-go-v2/service/s3\"\n\t\"github.com/aws/aws-sdk-go-v2/service/sts\"\n\n\tawscompat \"github.com/salrashid123/awscompat\"\n\t\"google.golang.org/api/idtoken\"\n)\n\nconst ()\n\nfunc main() {\n\n\taud := \"https://foo.bar\"\n\tjsonCert := \"/path/to/svc.json\"\n\n\tctx := context.Background()\n\tts, err := idtoken.NewTokenSource(ctx, aud, idtoken.WithCredentialsFile(jsonCert))\n\t// or on GCE/GKE/Run/GCF, omit the certificate file\n\t//ts, err := idtoken.NewTokenSource(ctx, aud)\n\tif err != nil {\n\t\tlog.Fatalf(\"unable to create TokenSource: %v\", err)\n\t}\n\n\tregion := \"us-east-2\"\n\tcreds, err := awscompat.NewGCPAWSCredentials(ts, region, \u0026sts.AssumeRoleWithWebIdentityInput{\n\t\tRoleArn:         aws.String(\"arn:aws:iam::291738886548:role/s3role\"),\n\t\tRoleSessionName: aws.String(\"app1\"),\n\t})\n\tif err != nil {\n\t\tlog.Fatalf(\"Error creating Credentials  %v\", err)\n\t}\n\n\tcfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(region), config.WithCredentialsProvider(creds))\n\n\ts3client := s3.NewFromConfig(cfg)\n\n\tsresp, err := s3client.ListObjectsV2(context.Background(), \u0026s3.ListObjectsV2Input{Bucket: aws.String(\"mineral-minutia\")})\n\tif err != nil {\n\t\tlog.Fatalf(\"Error listing objects:  %v\", err)\n\t}\n\n\tfor _, item := range sresp.Contents {\n\t\tfmt.Printf(\"Name %v  %v\\n:\", time.Now(), *item.Key)\n\t}\n\n}\n\n```\n\nJust note\n\n- `\"google.golang.org/api/idtoken\"` will only provide `id_tokens` for service accounts.   It does not support user-based id_tokens.\n\n\n---\n\n\n#### Java\n\nIn Java, the `GCPAWSCredentialProviderl` is included directly in this repo (`java/src/main/java/com/google/awscompat/GCPAWSCredentialProvider.java`) as well as the test app  that acquired googleID tokens from various sources`java/src/main/java/com/test/Main.java`\n\n```java\n\n          // Using default ProcessCredentials\n          // AmazonS3 s3 =\n          // AmazonS3ClientBuilder.standard().withRegion(Regions.US_EAST_2).build();\n\n          // or\n          // Get an IDToken from the source system.\n          // IdTokenCredentials tok = tc.getIDTokenFromComputeEngine(target_audience);\n\n          // in this case, its using a service account file:\n          ServiceAccountCredentials sac = ServiceAccountCredentials.fromStream(new FileInputStream(credFile));\n          sac = (ServiceAccountCredentials) sac.createScoped(Arrays.asList(CLOUD_PLATFORM_SCOPE));\n\n          IdTokenCredentials tok = tc.getIDTokenFromServiceAccount(sac, target_audience);\n\n          // then specify the GCPAWSCredentialProvider.googleCredential() value\n          String roleArn = \"arn:aws:iam::291738886548:role/s3webreaderrole\";\n          AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion(Regions.US_EAST_2)\n                    .withCredentials(GCPAWSCredentialProvider.builder().roleArn(roleArn).roleSessionName(null)\n                              .googleCredentials(tok).build())\n                    .build();\n\n```\n\n#### Python\n\nFor Python, a similar flow to acquire a google ID token manually and then add the raw `SessionToken` value in:\n\n```python\n# For other sources of IDTokens, see\n#  https://github.com/salrashid123/google_id_token/blob/master/python/googleidtokens.py#L33\n\ndef getIdToken():\n    svcAccountFile =\"/path/to/svc.json\"\n    target_audience=\"https://sts.amazonaws.com\"\n    creds = service_account.IDTokenCredentials.from_service_account_file(\n            svcAccountFile,\n            target_audience= target_audience)\n    request = google.auth.transport.requests.Request()\n    creds.refresh(request)\n    return creds.token\n\n\n# Using Specify Credentials and SessionToken\nsts_client = boto3.client('sts')\n\nassumed_role_object = sts_client.assume_role_with_web_identity(\n    RoleArn=\"arn:aws:iam::291738886548:role/s3webreaderrole\",\n    RoleSessionName=\"AssumeRoleSession1\",\n    WebIdentityToken=getIdToken(),\n    DurationSeconds=900\n)\ncredentials = assumed_role_object['Credentials']\n\ns3_resource = boto3.resource(\n    's3',\n    aws_access_key_id=credentials['AccessKeyId'],\n    aws_secret_access_key=credentials['SecretAccessKey'],\n    aws_session_token=credentials['SessionToken'],\n)\n\nbkt = s3_resource.Bucket('mineral-minutia')\nfor my_bucket_object in bkt.objects.all():\n    print(my_bucket_object)\n```\n\nTo Note, the `boto3.resource()` takes the raw value of the `SessionToken` which means once it expires, the `s3_resource` will also fail and not renew.\n\nI haven't been able to figure out how to create a managed `Credential` object in AWS python boto library set that would handle the refresh of the underlying token for you.\n\nAnother approach would be to use a `CredentialProvier` as shown in [here](https://github.com/salrashid123/cloud_auth_tpm/blob/main/cloud_auth_tpm/aws/awscredentials.py)\n\n#### Dotnet\n\nFor dotnet, you can either acquire a GoogleOIDC token and inject it into a static STS client or use the wrapped `GoogleCompatCredentials` object provided in this repo\n\n```csharp\n  public class GoogleCompatCredentials : RefreshingAWSCredentials\n```\n\nThe usage of both modes is shown in `dotnet/Main.cs` while if you just want to use the wrapped version:\n\nYou can bootstrap `GoogleCompatCredentials`  using any Google source Credential object that implements its `Google.Apis.Auth.OAuth2.IOidcTokenProvider` interface.  In the case below, its using `ServiceAccountCredential`\n\n```csharp\n                ServiceAccountCredential saCredential;\n                using (var fs = new FileStream(CREDENTIAL_FILE_JSON, FileMode.Open, FileAccess.Read))\n                {\n                    saCredential = ServiceAccountCredential.FromServiceAccountData(fs);\n                }\n                var getSessionTokenRequest = new AssumeRoleWithWebIdentityRequest\n                {\n                    RoleSessionName = \"testsession\",\n                    RoleArn = roleArn,\n                };\n                var targetAudience = \"https://sts.amazonaws.com/\";  // this can be any value (not used in this example)\n                var cc = new GoogleCompatCredentials(saCredential, targetAudience, getSessionTokenRequest);\n                using (s3Client = new AmazonS3Client(cc, bucketRegion))\n                {\n                    var listObjectRequest = new ListObjectsRequest\n                    {\n                        BucketName = bucketName\n                    };\n                    ListObjectsResponse response = await s3Client.ListObjectsAsync(listObjectRequest);\n                    List\u003cS3Object\u003e objects = response.S3Objects;\n                    foreach (S3Object o in objects)  {\n                       Console.WriteLine(\"Object  = {0}\", o.Key);\n                    }\n                }\n```\n\n#### nodejs\n\nFor node, you can either acquire a GoogleOIDC token and inject it into a static STS client or use the wrapped `GoogleCompatCredentials` object provided in this repo\n\n\n```javascript\nconst AWS = require('aws-sdk');\nconst { GoogleAuth } = require('google-auth-library');\n\nAWS.config.region = 'us-east-2';\n\nrequire('./google_compat_credentials.js');\n\nconst audience = 'https://sts.amazonaws.com/';\nconst roleArn = 'arn:aws:iam::291738886548:role/s3webreaderrole';\n\n\n  const auth = new GoogleAuth();\n  const client = await auth.getIdTokenClient(\n    audience\n  );\n\n\n  AWS.config.credentials = new GoogleCompatCredentials({\n    RoleArn: roleArn,\n    RoleSessionName: \"testsession\"\n  }, client);\n\n  var s3 = new AWS.S3();\n  var params = {\n    Bucket: 'mineral-minutia',\n  }\n  s3.listObjects(params, function (err, data) {\n    if (err) throw err;\n    console.log(data);\n  });\n\n```\n\n### Firebase/Identity Platform OIDC\n\nFirebase and [Identity Platform](https://cloud.google.com/identity-platform) can also provide OIDC tokens.  For example, the OIDC `.well-known` endpoint below for a given Firebase Project is discoverable by AWS as an external provider:\n\nFor my Firebase/Cloud Identity Platform Project, (called `mineral-minutia-820` below):\n\n- [https://securetoken.google.com/mineral-minutia-820/.well-known/openid-configuration](https://securetoken.google.com/mineral-minutia-820/.well-known/openid-configuration)\n\n\nand compare that with the full OIDC capabilities of google:\n\n- [https://accounts.google.com/.well-known/openid-configuration](https://accounts.google.com/.well-known/openid-configuration)\n\nBut thats enough to get started.  Unfortunately, there doesn't seem to be a golan library to wrap as shown earlier.   The following shows how to get a Firebase id_token using its nodeJS library using plain `firebase.auth().signInWithEmailAndPassword`\n\n```javascript\nrequire(\"firebase/auth\");\n\nconst email = \"your@email.com\";\nconst password = \"yourpassword\";\nvar firebaseConfig = {\n    apiKey: \"...\",\n    authDomain: \"...\",\n    projectId: \"...\",\n    storageBucket: \"...\",\n  };\n\nfirebase.initializeApp(firebaseConfig);\nfirebase.auth().signInWithEmailAndPassword(email, password).then(result =\u003e {\n  firebase.auth().currentUser.getIdToken(true).then(function(idToken) {\n    console.log(idToken);\n  }\n}\n```\nYou can find a sample Firebase app that acquires an `id_token` here:\n\n[Firebase Storage and Authorization Rules engine 'helloworld'](https://blog.salrashid.me/posts/firebase_storage_rules/)\n\nOnce you have the id_token, decode as done earlier to fin the `sub` value.  THis will be unique to each Firebase project even if the same actual user logs into multiple projects.\n\n\n\nFirst define an external provider:\n\n![images/gcpip_provider.png](images/gcpip_provider.png)\n\nWhen you specify the endpoint configuration for OIDC, just use the root URL for the discovery endpoint with the firebase projectID: `https://securetoken.google.com/mineral-minutia-820`\n\nThen define a Role with the external provider:  in my case the role was `arn:aws:iam::291738886548:role/cicps3role`\n\n![images/gcpip_role.png](images/gcpip_role.png)\n\n```json\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Principal\": {\n        \"Federated\": \"arn:aws:iam::291738886548:oidc-provider/securetoken.google.com/mineral-minutia-820\"\n      },\n      \"Action\": \"sts:AssumeRoleWithWebIdentity\",\n      \"Condition\": {\n        \"StringEquals\": {\n          \"securetoken.google.com/mineral-minutia-820:aud\": \"mineral-minutia-820\",\n          \"securetoken.google.com/mineral-minutia-820:sub\": \"WQoGf9wuwiVtxal5AapvPIfb8Q43\"\n        }\n      }\n    }\n  ]\n}\n```\n\nThe `sub` value is taken from the decoded `id_token`\n\n```json\n{\n  \"name\": \"sal a mander\",\n  \"admin\": true,\n  \"groupId\": \"12345\",\n  \"iss\": \"https://securetoken.google.com/mineral-minutia-820\",\n  \"aud\": \"mineral-minutia-820\",\n  \"auth_time\": 1590897853,\n  \"user_id\": \"WQoGf9wuwiVtxal5AapvPIfb8Q43\",\n  \"sub\": \"WQoGf9wuwiVtxal5AapvPIfb8Q43\",\n  \"iat\": 1590897853,\n  \"exp\": 1590901453,\n  \"email\": \"sal@somedomain.com\",\n  \"email_verified\": false,\n  \"firebase\": {\n    \"identities\": {\n      \"email\": [\n        \"sal@somedomain.com\"\n      ]\n    },\n    \"sign_in_provider\": \"password\"\n  }\n}\n```\n\nAs mentioned, the there is no golang library for FireBase so a direct invocation w/ curl will yeld the AWS Credential.\n\n```bash\n$  curl -s \"https://sts.amazonaws.com/?Action=AssumeRoleWithWebIdentity\u0026DurationSeconds=3600\u0026RoleSessionName=app1\u0026RoleArn=arn:aws:iam::291738886548:role/cicps3role\u0026WebIdentityToken=$TOKEN\u0026Version=2011-06-15\u0026alt=json\"\n```\n\n```xml\n\u003cAssumeRoleWithWebIdentityResponse xmlns=\"https://sts.amazonaws.com/doc/2011-06-15/\"\u003e\n  \u003cAssumeRoleWithWebIdentityResult\u003e\n    \u003cAudience\u003emineral-minutia-820\u003c/Audience\u003e\n    \u003cAssumedRoleUser\u003e\n      \u003cAssumedRoleId\u003eAROAUH3H6EGKDE7GWMPWA:app1\u003c/AssumedRoleId\u003e\n      \u003cArn\u003earn:aws:sts::291738886548:assumed-role/cicps3role/app1\u003c/Arn\u003e\n    \u003c/AssumedRoleUser\u003e\n    \u003cProvider\u003earn:aws:iam::291738886548:oidc-provider/securetoken.google.com/mineral-minutia-820\u003c/Provider\u003e\n    \u003cCredentials\u003e\n      \u003cAccessKeyId\u003eASIAUH3H6EGKPJ...\u003c/AccessKeyId\u003e\n      \u003cSecretAccessKey\u003eZ3S78e6hWYGlub6YlOgz6hYwo81...\u003c/SecretAccessKey\u003e\n      \u003cSessionToken\u003eFwoGZXIvYXd...\u003c/SessionToken\u003e\n      \u003cExpiration\u003e2020-05-31T05:11:05Z\u003c/Expiration\u003e\n    \u003c/Credentials\u003e\n    \u003cSubjectFromWebIdentityToken\u003eWQoGf9wuwiVtxal5AapvPIfb8Q43\u003c/SubjectFromWebIdentityToken\u003e\n  \u003c/AssumeRoleWithWebIdentityResult\u003e\n  \u003cResponseMetadata\u003e\n    \u003cRequestId\u003e5959ed62-13ac-4205-a0f6-811f00bced6b\u003c/RequestId\u003e\n  \u003c/ResponseMetadata\u003e\n\u003c/AssumeRoleWithWebIdentityResponse\u003e\n```\n\nOne more note about Firebase/Cloud Identity Platform:  You can use it to define external identities itself (eg, Google, Facebook, AOL, other OIDC, other SAML, etc).\n\nThat means you can chain identities together though Identity Platform.   \n\nTurtles all the way down (or atleast a couple of levels).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Fawscompat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsalrashid123%2Fawscompat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Fawscompat/lists"}