{"id":21354919,"url":"https://github.com/salrashid123/sts_server","last_synced_at":"2025-07-12T22:32:25.158Z","repository":{"id":58819585,"uuid":"309153360","full_name":"salrashid123/sts_server","owner":"salrashid123","description":"Serverless Security Token Exchange Server(STS) and gRPC STS credentials","archived":false,"fork":false,"pushed_at":"2024-04-01T13:37:48.000Z","size":3724,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-04-01T14:55:24.847Z","etag":null,"topics":["golang","grpc","sts"],"latest_commit_sha":null,"homepage":"","language":"Go","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}},"created_at":"2020-11-01T17:45:41.000Z","updated_at":"2023-06-24T19:03:09.000Z","dependencies_parsed_at":"2024-04-01T14:47:04.061Z","dependency_job_id":"1973386e-334e-41f3-9ecd-c6553eee23ba","html_url":"https://github.com/salrashid123/sts_server","commit_stats":{"total_commits":13,"total_committers":1,"mean_commits":13.0,"dds":0.0,"last_synced_commit":"d6093265527dae0bed0c267f677b11406278a8ed"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fsts_server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fsts_server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fsts_server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fsts_server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/salrashid123","download_url":"https://codeload.github.com/salrashid123/sts_server/tar.gz/refs/heads/main","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":["golang","grpc","sts"],"created_at":"2024-11-22T04:15:20.071Z","updated_at":"2024-11-22T04:15:20.832Z","avatar_url":"https://github.com/salrashid123.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Serverless Security Token Exchange Server(STS) and gRPC STS credentials\n\n\nThis repo contains a very basic STS server deployed on [Cloud Run](https://cloud.google.com/run/docs) which exchanges a one `access_token` for another....basically, a token broker described here:\n\n- [rfc8693: OAuth 2.0 Token Exchange](https://tools.ietf.org/html/rfc8693)\n\nThe STS server here is *not* a reference implementation..just use this as a helloworld tutorial\n\nThis particular STS server exchanges one static access token for another.   It will exchange \n\n* `iamtheeggman`  for  `iamthewalrus`   (right, thats it..)\n\n\nYou can use an http client `curl` to see the exchange directly and then use a new gRPC client which utilizes its own gRPC STS Credential object:\n\n\n\u003e\u003e This is not an officially supported Google product\n\n---\n\nThis tutorial will deploy \n\n* `gRPC server` on Cloud Run that will inspect the `Authoriztion` header and only allow the request if the value is `iamthewalrus`\n* `STS server` on Cloud Run that will only provide the token exchange if the inbound token is `iamtheeggman`\n* `gRPC client` that will use the STS Credential object to access the gRPC server after it performs the exchange.\n\nthen if you want\n\n* `http_server` locally which will inspect the `Authoriztion` header and only allow the request if the value is `iamthewalrus`\n* `http_client` uses a the sts client library from `https://github.com/salrashid123/sts/tree/main/http` to perform the exchange and send the final token to an endpoint\n\n\nfirst gRPC\n\n### gRPC\n\nCreate a file with the original token:\n\n```bash\nmkdir /tmp/stscreds\necho -n iamtheeggman \u003e /tmp/stscreds/creds.txt\n```\n\n\nSetup the environment variables and deploy the gRPC and STS servers to cloud run\n```bash\nexport PROJECT_ID=`gcloud config get-value core/project`\nexport PROJECT_NUMBER=`gcloud projects describe $PROJECT_ID --format='value(projectNumber)'`\n```\n\n#### Deploy gRPC Server\n\n```bash\ncd server/\ndocker build -t gcr.io/$PROJECT_ID/grpc_server .\ndocker push gcr.io/$PROJECT_ID/grpc_server\n\ngcloud  run deploy grpcserver  \\\n  --image gcr.io/$PROJECT_ID/grpc_server \\\n  --allow-unauthenticated  --region us-central1  --platform=managed  -q\n```\n\n#### Deploy STS Server\n\n```bash\ncd sts_server/\ndocker build -t gcr.io/$PROJECT_ID/sts_server .\ndocker push gcr.io/$PROJECT_ID/sts_server\n\ngcloud run deploy stsserver  --image gcr.io/$PROJECT_ID/sts_server \\\n --region us-central1  --allow-unauthenticated --platform=managed  -q\n```\n\n### gRPC Client\n\n\nFirst we need to find the assigned addresses for the gRPC server and the STS Server\n\n```bash\ncd client/\n\nexport GRPC_SERVER_ADDRESS=`gcloud run services describe grpcserver --format=\"value(status.url)\"`\nexport GRPC_SERVER_ADDRESS=`echo \"$GRPC_SERVER_ADDRESS\" | awk -F/ '{print $3}'`\necho $GRPC_SERVER_ADDRESS\n\nexport STS_URL=`gcloud run services describe stsserver --format=\"value(status.url)\"`/token\necho $STS_URL\n\n\nexport GRPC_GO_LOG_VERBOSITY_LEVEL=99\nexport GRPC_GO_LOG_SEVERITY_LEVEL=info\n\ngo run grpc_client.go \\\n  --address $GRPC_SERVER_ADDRESS:443 \\\n  --cacert googleCA.crt \\\n  --servername $GRPC_SERVER_ADDRESS \\\n  --stsaddress $STS_URL \\\n  --usetls \\\n  --stsCredFile /tmp/stscreds/creds.txt\n\n## note, you can get googleCA.crt by copying in `openssl s_client $GRPC_SERVER_ADDRESS:443`\n```\n\nok, how does this work with gRPC?  Well you just have to specify the STS Credential type as credential object with the specifications of the STS configurations.\n\nIn the command set below, we're specifying the rest endpoint of the STS server, and critically the `SubjectTokenPath` which is the path to the file where we saved the source token.\n\nOnce you specify all this, the grpc Client will do the legwork to exchange the source token for the remote one\n\n\u003e Note: i'm using my own sts credential provider `\"github.com/salrashid123/sts_server/sts\"` which is a fork of `\"google.golang.org/grpc/credentials/sts\"` until [issue  5611](https://github.com/grpc/grpc-go/pull/5611) is merged \n\n```golang\nimport (\n\t//\"google.golang.org/grpc/credentials/sts\"\n\t\"github.com/salrashid123/sts_server/sts\"\n)\n\n\t\tstscreds, err := sts.NewCredentials(sts.Options{\n\t\t\tTokenExchangeServiceURI: *stsaddress,\n\t\t\tResource:                *stsaudience,\n\t\t\tAudience:                *stsaudience,\n\t\t\tScope:                   *scope,\n\t\t\tSubjectTokenPath:        *stsCredFile,\n\t\t\tSubjectTokenType:        \"urn:ietf:params:oauth:token-type:access_token\",\n\t\t\tRequestedTokenType:      \"urn:ietf:params:oauth:token-type:access_token\",\n\t\t\tHTTPClient:              http.DefaultClient,\n\t\t})\n\n\t\tconn, err = grpc.Dial(*address,\n\t\t\tgrpc.WithTransportCredentials(ce),\n\t\t\tgrpc.WithPerRPCCredentials(stscreds))    \n```\n\n.....now...why is specifying the `SubjectTokenPath` a _file_?  I don't know..at the very least it should be `[]byte` or perhaps an `oauth2.TokenSource` which includes the value of the source token.  I'll file a bug about this. In the meantime, the code contained [here](https://gist.github.com/salrashid123/c9c3863a681b5a8f61c0012ae9d01fcc#file-sts-go-L274) is copy of the grpc sts.go file defines and uses `SubjectTokenSource`.\n\nThe usage for this in the client would look like \n\n```golang\n\t\tstscreds, err := sts.NewCredentials(sts.Options{\n\t\t\tTokenExchangeServiceURI: *stsaddress,\n\t\t\tResource:                *stsaudience,\n\t\t\tAudience:                *stsaudience,\n\t\t\tScope:                   *scope,\n\t\t\t//SubjectTokenPath:        *stsCredFile,\n\t\t\tSubjectTokenSource: oauth2.StaticTokenSource(\u0026oauth2.Token{\n\t\t\t\tAccessToken: \"iamtheeggman\",\n\t\t\t\tExpiry:      time.Now().Add(time.Duration(300 * time.Second)),\n\t\t\t}),\t\t\t\n\t\t\tSubjectTokenType:        \"urn:ietf:params:oauth:token-type:access_token\",\n\t\t\tRequestedTokenType:      \"urn:ietf:params:oauth:token-type:access_token\",\n\t\t\t//HttpClient:     http.DefaultClient,\n\t\t})\n```\n\nAlternatively, just to test,you can inject a [test TokenSource](https://github.com/salrashid123/oauth2#usage-dummytokensource) instead of the static on.\n\n### curl\n\nIf you just want to see the formats accepted by the STS server, you can use the commands shown below\n\n\n- as `application/x-www-form-urlencoded`\n\n```bash\n$ cd curl/\n$ curl -s -H \"Content-Type: application/x-www-form-urlencoded\"  -d @sts_req.txt  $STS_URL | jq '.'\n{\n  \"access_token\": \"iamthewalrus\",\n  \"issued_token_type\": \"urn:ietf:params:oauth:token-type:access_token\",\n  \"token_type\": \"Bearer\",\n  \"expires_in\": 60\n}\n```\n\n- as `application/json`\n\n```bash\n$ cd curl/\n$ curl -s -X POST -H \"Content-Type: application/json\" -d @sts_req.json  $STS_URL | jq '.'\n{\n  \"access_token\": \"iamthewalrus\",\n  \"issued_token_type\": \"urn:ietf:params:oauth:token-type:access_token\",\n  \"token_type\": \"Bearer\",\n  \"expires_in\": 60\n}\n```\n\nNote the two source files contains the specifications of the source token that will get sent to the STS server\n\n```json\n{\n    \"grant_type\": \"urn:ietf:params:oauth:grant-type:token-exchange\",\n    \"resource\": \"grpcserver-3kdezruzua-uc.a.run.app\",\n    \"audience\": \"grpcserver-3kdezruzua-uc.a.run.app\",\n    \"requested_token_type\": \"urn:ietf:params:oauth:token-type:access_token\",\n    \"subject_token\": \"iamtheeggman\",\n    \"subject_token_type\": \"urn:ietf:params:oauth:token-type:access_token\"\n}\n```\n\nIf you change the value of the `subject_token`, the STS server will reject the request.\n\nif you want to, edit the  files and replace the values for `resource` and `audience` with `$GRPC_SERVER_ADDRESS` (its a no-op since this isn't used in this STS server )\n\n---\n\n## STSTokenSource Server demo using HTTP Client\n\nThe following bootstraps STS Credentials *from* and *to* an [oauth2.TokenSource](https://godoc.org/golang.org/x/oauth2#TokenSource).\n\nThis basically means you can inject any token into a TokenSource and then utilize an unsupported library here:\n [https://github.com/salrashid123/oauth2#usage-sts](https://github.com/salrashid123/oauth2#usage-sts)\n\nto derive a new tokensource based off an STS server.\n\nI'm using an oauth2 token source here but clearly, the source and target tokensources need not be oauth2.\n\n\u003e\u003e this is not supported by google and neither is `github.com/salrashid123/oauth2/sts`\n\nYou must first deploy the STS Server into cloud run as shown in the root repo.\n\n### Start HTTP Server\n\n```bash\ncd http_server\ngo run server.go\n```\n\n### Start Client\n\n```bash\n$ go run client.go --stsaddress https://stsserver-3kdezruzua-uc.a.run.app/token --endpoint https://httpbin.org/get\n\n2023/10/27 13:20:14 New Token: iamthewalrus\n2023/10/27 13:20:14 {\n  \"args\": {}, \n  \"headers\": {\n    \"Accept-Encoding\": \"gzip\", \n    \"Authorization\": \"Bearer iamthewalrus\", \n    \"Host\": \"httpbin.org\", \n    \"User-Agent\": \"Go-http-client/2.0\", \n    \"X-Amzn-Trace-Id\": \"Root=1-653bf14e-6f28f7843667ed806be1e4bc\"\n  }, \n  \"origin\": \"108.51.25.168\", \n  \"url\": \"https://httpbin.org/get\"\n}\n\n$ go run client.go --stsaddress https://stsserver-3kdezruzua-uc.a.run.app/token --endpoint http://localhost:8080/\n2023/10/27 13:20:27 New Token: iamthewalrus\n2023/10/27 13:20:27 ok\n\n```\n\nThe following snippet shows the exchange happening from a source token \"iamtheeggman\" to a destination tokensource that will automatically perform the STS Exchange.\n\n\nOne the exchange takes place, a plain authorized request \n```golang\nimport (\n   \tsal \"github.com/salrashid123/sts/http\"\n)\n\n\tclient := \u0026http.Client{}\n\n    // start with a source tken\n\trootTS := oauth2.StaticTokenSource(\u0026oauth2.Token{\n\t\tAccessToken: \"iamtheeggman\",\n\t\tTokenType:   \"Bearer\",\n\t\tExpiry:      time.Now().Add(time.Duration(time.Second * 60)),\n    })\n    \n    // exchange it\n\tstsTokenSource, _ := sal.STSTokenSource(\n\t\t\u0026sal.STSTokenConfig{\n\t\t\tTokenExchangeServiceURI: \"https://https://stsserver-3kdezruzua-uc.a.run.app/token\",\n\t\t\tResource:                \"localhost\",\n\t\t\tAudience:                \"localhost\",\n\t\t\tScope:                   \"https://www.googleapis.com/auth/cloud-platform\",\n\t\t\tSubjectTokenSource:      rootTS,\n\t\t\tSubjectTokenType:        \"urn:ietf:params:oauth:token-type:access_token\",\n\t\t\tRequestedTokenType:      \"urn:ietf:params:oauth:token-type:access_token\",\n\t\t\t//HttpClient:     http.DefaultClient,\n\t\t},\n    )\n    \n    // print the new token (iamthewalrus)\n\ttok, err := stsTokenSource.Token()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tlog.Printf(\"New Token: %s\", tok.AccessToken)    \n\n    // use the new token\n\tclient = oauth2.NewClient(context.TODO(), stsTokenSource)\n\tresp, err := client.Get(\"http://localhost:8080/\")\n\tif err != nil {\n\t\tlog.Printf(\"Error creating client %v\", err)\n\t\treturn\n    }\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Fsts_server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsalrashid123%2Fsts_server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Fsts_server/lists"}