summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2022-04-13 09:44:31 -0600
committermo khan <mo@mokhan.ca>2022-04-13 09:44:31 -0600
commitf50684ff437d7880272b34de189c3d0421b0b44d (patch)
tree3766c825ec4a2c31736d73bab3e23bb704cb911a
parentc20c22779c0f6e8db2d028a5ad1ee6dbba08008b (diff)
update notes on oidc flow
-rw-r--r--doc/run-identity/README.md209
-rwxr-xr-xsrc/oidc/bin/01_authz_code2
-rwxr-xr-xsrc/oidc/bin/02_authz_code_token_request19
3 files changed, 190 insertions, 40 deletions
diff --git a/doc/run-identity/README.md b/doc/run-identity/README.md
index 8587512..a83929d 100644
--- a/doc/run-identity/README.md
+++ b/doc/run-identity/README.md
@@ -23,10 +23,9 @@ Related Field Requests:
To Learn:
-* [ ] the OIDC flows.
-* [ ] the Vault API.
-* [ ] the key material available to a Terraform run context.
-
+* [X] the OIDC flows.
+* [X] the Vault API.
+* [X] the key material available to a Terraform run context.
1. In cloud provider, create OIDC trust between cloud role and TFC Workspace.
1. In run task, generate a token via OIDC Provider before apply step.
@@ -34,40 +33,174 @@ To Learn:
```plaintext
-Is it like this?
- ------- ---------------- ----------
- | TFC | | OIDC Provider| | runner |
- ------- ---------------- ----------
- | | |
- |--- request token ----->| |
- | | |
- |<----- return token ----| |
- | |
- | |
- | |
- |---- inject secrets ---------------------->|
-
-or like this ...
-
- ------- ---------- ---------
- | TFC | | Runner | | Vault |
- ------- ---------- ---------
- * aws access/secret
- -------->
- * job description
- * a way to get key material from Vault. (token)
- * config version data.
- --------> give me the secrets
- * do the thing
- <------- return the job status
-
-1. schedule run of apply.
-2. key material to do the apply.
- * aws access/secret key
- * environment vars
-3. low ttl key material to do the things.
+ |<--- 1. fetch .well-known/openid-configuration
+ | |
+ |---- 2. return public keys ------->|
+ | |
+ ------- ---------------- ---------- ---------------------
+ | TFC | | OIDC Provider| | runner | | AWS/Azure/GCP/Vault |
+ ------- ---------------- ---------- ---------------------
+ | | | |
+ |- 3. request id token ->| | |
+ | | | |
+ |<-4. return id token ---| | |
+ | | |
+ |>--5. provide id token ------------------------------------>|
+ | |
+ |<---6. return secrets ------------------------------------<|
+ | | |
+ |---7. inject secrets ------------------->| |
+ | |
+ |-- 8. do things ->|
```
+1. the identity provider is registered with AWS/Azure/GCP/Vault.
+ * the `/.well-known/openid-configuration` endpoint is used to fetch metadata.
+2. the openid metadata is returned.
+ * this metadata is used to validate the integrity of JWT's that it receives in step 5.
+ ```bash
+ モ curl https://dev-klipadbq.us.auth0.com/.well-known/openid-configuration | jq
+ {
+ "issuer": "https://dev-klipadbq.us.auth0.com/",
+ "authorization_endpoint": "https://dev-klipadbq.us.auth0.com/authorize",
+ "token_endpoint": "https://dev-klipadbq.us.auth0.com/oauth/token",
+ "device_authorization_endpoint": "https://dev-klipadbq.us.auth0.com/oauth/device/code",
+ "userinfo_endpoint": "https://dev-klipadbq.us.auth0.com/userinfo",
+ "mfa_challenge_endpoint": "https://dev-klipadbq.us.auth0.com/mfa/challenge",
+ "jwks_uri": "https://dev-klipadbq.us.auth0.com/.well-known/jwks.json",
+ "registration_endpoint": "https://dev-klipadbq.us.auth0.com/oidc/register",
+ "revocation_endpoint": "https://dev-klipadbq.us.auth0.com/oauth/revoke",
+ "scopes_supported": [
+ "openid",
+ "profile",
+ "offline_access",
+ "name",
+ "given_name",
+ "family_name",
+ "nickname",
+ "email",
+ "email_verified",
+ "picture",
+ "created_at",
+ "identities",
+ "phone",
+ "address"
+ ],
+ "response_types_supported": [
+ "code",
+ "token",
+ "id_token",
+ "code token",
+ "code id_token",
+ "token id_token",
+ "code token id_token"
+ ],
+ "code_challenge_methods_supported": [
+ "S256",
+ "plain"
+ ],
+ "response_modes_supported": [
+ "query",
+ "fragment",
+ "form_post"
+ ],
+ "subject_types_supported": [
+ "public"
+ ],
+ "id_token_signing_alg_values_supported": [
+ "HS256",
+ "RS256"
+ ],
+ "token_endpoint_auth_methods_supported": [
+ "client_secret_basic",
+ "client_secret_post"
+ ],
+ "claims_supported": [
+ "aud",
+ "auth_time",
+ "created_at",
+ "email",
+ "email_verified",
+ "exp",
+ "family_name",
+ "given_name",
+ "iat",
+ "identities",
+ "iss",
+ "name",
+ "nickname",
+ "phone_number",
+ "picture",
+ "sub"
+ ],
+ "request_uri_parameter_supported": false
+ }
+ ```
+3. TFC starts a plan, apply etc. by requesting (generating?) an `id_token`
+ * `id_token` can be obtained via an authz code flow, implicit flow or hybrid flow.
+ ```bash
+ curl -s \
+ -u "client_id:client_secret" \
+ --basic \
+ -d "grant_type=authorization_code&code=example&redirect_uri=http://localhost:3000/oauth/callback" \
+ "https://dev-klipadbq.us.auth0.com/oauth/token"
+ ```
+4. the `id_token` that is returned is a signed JWT
+ * signature is a hash of content encrypted with private key.
+ * signature can be decrypted by public key found in metadata exchange.
+ * hash is recomputed by aws to ensure that the data hasn't been tampered with.
+ ```json
+ {
+ "access_token":"eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiaXNzIjoiaHR0cHM6Ly9kZXYta2xpcGFkYnEudXMuYXV0aDAuY29tLyJ9..kpYUjY8jDc2kRVat.noMdBQplkqhibQhYsz5pWr84Y9KkYl5XsS4IPQhq0EOa0nsy7tqAyH0viGKsFNZ2qxnckE2qk7YqDPGsbgSR_pQlsxGODllWEjVxhRRSDehHkWf9h5rBsMS0bVPbHRbRp_z9hSmzXdtd3xRWHgMN35tu3cylRqnWLgp4bVZF8UA4sEPHe6wZFWrkPq_YCYhTDGoFsxk-6WXy4_r6xKIttWeXKEA0bTADsERKBTfRNI5F7F4-iTHd9VQl4HItoRfDz48cp86LD1AiuES-mMtPgP9HaWbqo9O4UDk9NXs_awhKfyNy.uNjG1xpLDnc4Km9oHcFwNg",
+ "id_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlE2T2V2XzZTMkhDa3VKVFdQNzlrdCJ9.eyJpc3MiOiJodHRwczovL2Rldi1rbGlwYWRicS51cy5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NjI1NjM4ODhmN2YwZjUwMDY4M2Y3YTllIiwiYXVkIjoieW1oaDF0clo4VGNxVVBqM1hlWm96MjdLalhQaEFtaE8iLCJpYXQiOjE2NDk4MjMxNTMsImV4cCI6MTY0OTg1OTE1M30.R_zm-f2e6ZVKW73ycPXbBtoBk8gGNytiol4ET4RtNTmgTElFHNDUmyHJDTJbzyHACOju5RcR4o0kpwxdkCmZy7iQw1U4JphAhb1Na4wKHJqk7zn1wJ-hrHou7QGnuVufQTvLnxyxcF6AMc5gxi3CbQf1p5NH0JQpdgc7R-tiQDMV4sa7mWMdVVNHv7oIJFu7PKuPKkg9Aox71dtq-e5_Ucth7JNkDHV61xvJ3L6UoPk9BVDqj4pT84T_ucfKsREdS-_6_2vTneDycxl1UW7_e3UTXpvsaui87LKSBs4L2feOuWTxRL62-XKN--D02tLY6nLdu-OAFEnLy1NX8h0qqA",
+ "scope":"openid",
+ "expires_in":86400,
+ "token_type":"Bearer"
+ }
+ ```
+ ```irb
+ irb(main):001:0> require 'base64'
+ irb(main):002:0> x = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlE2T2V2XzZTMkhDa3VKVFdQNzlrdCJ9.eyJpc3MiOiJodHRwczovL2Rldi1rbGlwYWRicS51cy5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NjI1NjM4ODhmN2YwZjUwMDY4M2Y3YTllIiwiYXVkIjoieW1oaDF0clo4VGNxVVBqM1hlWm96MjdLalhQaEFtaE8iLCJpYXQiOjE2NDk4MjMxNTMsImV4cCI6MTY0OTg1OTE1M30.R_zm-f2e6ZVKW73ycPXbBtoBk8gGNytiol4ET4RtNTmgTElFHNDUmyHJDTJbzyHACOju5RcR4o0kpwxdkCmZy7iQw1U4JphAhb1Na4wKHJqk7zn1wJ-hrHou7QGnuVufQTvLnxyxcF6AMc5gxi3CbQf1p5NH0JQpdgc7R-tiQDMV4sa7mWMdVVNHv7oIJFu7PKuPKkg9Aox71dtq-e5_Ucth7JNkDHV61xvJ3L6UoPk9BVDqj4pT84T_ucfKsREdS-_6_2vTneDycxl1UW7_e3UTXpvsaui87LKSBs4L2feOuWTxRL62-XKN--D02tLY6nLdu-OAFEnLy1NX8h0qqA'
+ => "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlE2T2V2XzZTMkhDa3VKVFdQNzlrdCJ9.eyJpc3MiOiJodHRwczovL2Rldi1rbGlwYWRicS51cy5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NjI1NjM4ODhmN2YwZjUwMDY4M2Y3YTllIiwiYXVkIjoieW1oaDF0clo4VGNxVVBqM1hlWm96MjdLalhQaEFtaE8iLCJpYXQiOjE2NDk4MjMxNTMsImV4cCI6MTY0OTg1OTE1M...
+ irb(main):003:0> x.split('.')
+ =>
+ ["eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlE2T2V2XzZTMkhDa3VKVFdQNzlrdCJ9",
+ "eyJpc3MiOiJodHRwczovL2Rldi1rbGlwYWRicS51cy5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NjI1NjM4ODhmN2YwZjUwMDY4M2Y3YTllIiwiYXVkIjoieW1oaDF0clo4VGNxVVBqM1hlWm96MjdLalhQaEFtaE8iLCJpYXQiOjE2NDk4MjMxNTMsImV4cCI6MTY0OTg1OTE1M30",
+ "R_zm-f2e6ZVKW73ycPXbBtoBk8gGNytiol4ET4RtNTmgTElFHNDUmyHJDTJbzyHACOju5RcR4o0kpwxdkCmZy7iQw1U4JphAhb1Na4wKHJqk7zn1wJ-hrHou7QGnuVufQTvLnxyxcF6AMc5gxi3CbQf1p5NH0JQpdgc7R-tiQDMV4sa7mWMdVVNHv7oIJFu7PKuPKkg9Aox71dtq-e5_Ucth7JNkDHV61xvJ3L6UoPk9BVDqj4pT84T_ucfKsREdS-_6_2vTneDycxl1UW7_e3UTXpvsaui87LKSBs4L2feOuWTxRL62-XKN--D02tLY6nLdu-OAFEnLy1NX8h0qqA"]
+ irb(main):004:0> Base64.decode64(x.split('.')[0])
+ => "{\"alg\":\"RS256\",\"typ\":\"JWT\",\"kid\":\"Q6Oev_6S2HCkuJTWP79kt\"}"
+ irb(main):005:0> Base64.decode64(x.split('.')[1])
+ => "{\"iss\":\"https://dev-klipadbq.us.auth0.com/\",\"sub\":\"auth0|62563888f7f0f500683f7a9e\",\"aud\":\"ymhh1trZ8TcqUPj3XeZoz27KjXPhAmhO\",\"iat\":1649823153,\"exp\":1649859153}"
+ ```
+5. TFC sends the `id_token` to the token service for the cloud provider. e.g. [STS][1]
+ ```bash
+ モ aws sts assume-role-with-web-identity \
+ --role-arn "arn:aws:iam::119201842733:role/idp-web-identity-role" \
+ --role-session-name="example-1" \
+ --duration-seconds 3600 \
+ --web-identity-token="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlE2T2V2XzZTMkhDa3VKVFdQNzlrdCJ9.eyJpc3MiOiJodHRwczovL2Rldi1rbGlwYWRicS51cy5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NjI1NjM4ODhmN2YwZjUwMDY4M2Y3YTllIiwiYXVkIjoieW1oaDF0clo4VGNxVVBqM1hlWm96MjdLalhQaEFtaE8iLCJpYXQiOjE2NDk4MjMxNTMsImV4cCI6MTY0OTg1OTE1M30.R_zm-f2e6ZVKW73ycPXbBtoBk8gGNytiol4ET4RtNTmgTElFHNDUmyHJDTJbzyHACOju5RcR4o0kpwxdkCmZy7iQw1U4JphAhb1Na4wKHJqk7zn1wJ-hrHou7QGnuVufQTvLnxyxcF6AMc5gxi3CbQf1p5NH0JQpdgc7R-tiQDMV4sa7mWMdVVNHv7oIJFu7PKuPKkg9Aox71dtq-e5_Ucth7JNkDHV61xvJ3L6UoPk9BVDqj4pT84T_ucfKsREdS-_6_2vTneDycxl1UW7_e3UTXpvsaui87LKSBs4L2feOuWTxRL62-XKN--D02tLY6nLdu-OAFEnLy1NX8h0qqA" --output json | cat
+ ```
+6. Cloud provider returns secrets.
+ ```json
+ {
+ "Credentials": {
+ "AccessKeyId": "ASIARXQH3YYWQMPAN57M",
+ "SecretAccessKey": "nRDvl9q6xoDtvLhha16mOQse9r03XoL2Yw6yMtwp",
+ "SessionToken": "FwoGZXIvYXdzEL7//////////wEaDCdzgBb1TNJKqqghGSLXAim8vKlHEDn/MxcIsIWnPloA+muPpcvh27zTlKg0XOAVHP6gHudFZHtHJY3L6Lnisf6np/7rstaHqGQy6Fa9tr47KHZtkhQRaDcrpKMgGc9v3VqP4g72k3NNg2zgzWThJEfvNge/RyabpIY1oqju9rK9CS3I7y8ntW4e/8KTxeYIniWgAPBrFJlnDm+vahTtsg/04OkuL+iIpfI+FaUBzTdzZGaE3cKztJX1e/0NpmOGLx5HCkaF0tn9MeZBeSJ/Z/pF4fAZK12+uN0pLvZOkMta+lFhMWlbzqF6pPiruF6PUv6iGILyE85JA/uM6ZerV3RiF4YdxyO5NOnq4USRzdxLQq9IqD5aZNeT1ZnbDPZR4yhztni01t6MB5DtXpaweRdFGEK/cT0aquOGYjYs6qVjuZOnqrUdObBk/V9R9TYuhur2StzyWeXozWSehfr/j/qovO39y1Mo9J3ZkgYyJArNFYwaGf/X2emoBDq/Jl5V2hEiFxANPW7LAhquWzIwIjDQBA==",
+ "Expiration": "2022-04-13T05:17:56+00:00"
+ },
+ "SubjectFromWebIdentityToken": "auth0|62563888f7f0f500683f7a9e",
+ "AssumedRoleUser": {
+ "AssumedRoleId": "AROARXQH3YYWSI3UUY4XD:example-1",
+ "Arn": "arn:aws:sts::119201842733:assumed-role/idp-web-identity-role/example-1"
+ },
+ "Provider": "arn:aws:iam::119201842733:oidc-provider/dev-klipadbq.us.auth0.com/",
+ "Audience": "ymhh1trZ8TcqUPj3XeZoz27KjXPhAmhO"
+ }
+ ```
+7. TFC injects secrets into the `Run`. I don't know how. Config variables, maybe?
+8. The `Run` makes API calls to the cloud provider using the `AWS_ACCESS_KEY_ID` and`AWS_SECRET_KEY` env vars that were injected.
+
# Vault
Start the server:
@@ -151,5 +284,7 @@ Acceptance Criteria:
To think about:
1. NTP syncronization to ensure time matches from client to server.
+1. X.509 certificate expiration management?
1. Who is on the app-sec team? (Brian?)
-1. x.509 certificate expiration.
+
+[1]: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html
diff --git a/src/oidc/bin/01_authz_code b/src/oidc/bin/01_authz_code
index fa96133..427bd5f 100755
--- a/src/oidc/bin/01_authz_code
+++ b/src/oidc/bin/01_authz_code
@@ -4,3 +4,5 @@ set -e
cd "$(dirname "$0")/.."
curl -v -s "http://localhost:8282/authorize?response_type=code&scope=openid&client_id=f00d&state=potatoe&redirect_uri=https://client.example.org/callback"
+
+curl -v -s "https://dev-klipadbq.us.auth0.com/authorize?response_type=code&scope=openid&client_id=ymhh1trZ8TcqUPj3XeZoz27KjXPhAmhO&state=potatoe&redirect_uri=http://localhost:3000/oauth/callback"
diff --git a/src/oidc/bin/02_authz_code_token_request b/src/oidc/bin/02_authz_code_token_request
index 9e1f221..710a8c2 100755
--- a/src/oidc/bin/02_authz_code_token_request
+++ b/src/oidc/bin/02_authz_code_token_request
@@ -5,7 +5,20 @@ cd "$(dirname "$0")/.."
curl -s \
-vv \
- -u "client_id:client_secret" \
+ -u "ymhh1trZ8TcqUPj3XeZoz27KjXPhAmhO:FZv9M-ANpFMHN8hNvURSuAcuMkriQX9-Ltz49SqVFxCgclcBNrms-BOFjUrVwO6U" \
--basic \
- -d "grant_type=authorization_code&code=example&redirect_uri=https://client.example.org/callback" \
- "http://localhost:8282/token" | jq '.'
+ -d "grant_type=authorization_code&code=kO_gvoj1pTF3z34T7jxVzahdfuEpmJFiuv29KetV09Zcv&redirect_uri=http://localhost:3000/oauth/callback" \
+ "https://dev-klipadbq.us.auth0.com/oauth/token"
+
+
+# {
+# "access_token":"eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiaXNzIjoiaHR0cHM6Ly9kZXYta2xpcGFkYnEudXMuYXV0aDAuY29tLyJ9..kpYUjY8jDc2kRVat.noMdBQplkqhibQhYsz5pWr84Y9KkYl5XsS4IPQhq0EOa0nsy7tqAyH0viGKsFNZ2qxnckE2qk7YqDPGsbgSR_pQlsxGODllWEjVxhRRSDehHkWf9h5rBsMS0bVPbHRbRp_z9hSmzXdtd3xRWHgMN35tu3cylRqnWLgp4bVZF8UA4sEPHe6wZFWrkPq_YCYhTDGoFsxk-6WXy4_r6xKIttWeXKEA0bTADsERKBTfRNI5F7F4-iTHd9VQl4HItoRfDz48cp86LD1AiuES-mMtPgP9HaWbqo9O4UDk9NXs_awhKfyNy.uNjG1xpLDnc4Km9oHcFwNg",
+# "id_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlE2T2V2XzZTMkhDa3VKVFdQNzlrdCJ9.eyJpc3MiOiJodHRwczovL2Rldi1rbGlwYWRicS51cy5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NjI1NjM4ODhmN2YwZjUwMDY4M2Y3YTllIiwiYXVkIjoic2NaN2xRVkZReHliVjJrbzhqU2RYUm9rZ1hzSktFOUsiLCJpYXQiOjE2NDk4MjEyNjUsImV4cCI6MTY0OTg1NzI2NX0.kLGLXR_5qCXBKJCkh87iiXXqz3qVKW_q-19sGVZ5cRM9k6zIPZrtr-CerYAkc75uKxXYCbSrGVAnFUjSYRofz8f3m1n1jwScXnU3gJ0ZZza3p167_KfHfa6VZYtTjVSivCIP3gWfuddNPLNl5CQNN5UKzzmed1Qb5Vly3kHdwK-6DZIDArW39jJT65QnyHuTBMCt6l6yNgJ2Xg5b2tawFFzqwa1MbR-MHWtOP2dbhSEv_mPnqw_GyDeXa9UtEhshTAUCAxGuzSH-YKZOf0e2FjTZA_EhPNp0zywq7y627Ucjzy6P8HGg9y0-y0vb4se9LrxJMeuKjWRukgM-51BtRA",
+# "scope":"openid",
+# "expires_in":86400,
+# "token_type":"Bearer"
+# }
+
+
+# {"access_token":"eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiaXNzIjoiaHR0cHM6Ly9kZXYta2xpcGFkYnEudXMuYXV0aDAuY29tLyJ9..BtPj7UDZWyCL29Nt.0pBVp02RgDRxdw1qYif-zPWvgH-UWrxLCuZU8cM2fn-GEufPyZO379Fj33aiMQT72nhUUjYGGw6yDtSlQt6xxJj6C2NE7ELKQAAN97QeFnWgcyyc4uM6Bv7c0060iYX_poLbNS3qwtG63GShzT7aD6u8arG3sWjOo8UTNp4RhJ7FDVpifs5pTfEeDb90aHUb_1_8sokU9q-QrpXYoXfEiw-lIIEEE0AjRmD7kYWviB1Gvnl4iX_QCDsvUSfNflH7th_qsBElnijgzaUeiQWYn4YSCHfOB56D61jttpTIX2s9m2zy.qgmWnYJCUEqpI4ak-C-ctA","id_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlE2T2V2XzZTMkhDa3VKVFdQNzlrdCJ9.eyJpc3MiOiJodHRwczovL2Rldi1rbGlwYWRicS51cy5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NjI1NjM4ODhmN2YwZjUwMDY4M2Y3YTllIiwiYXVkIjoieW1oaDF0clo4VGNxVVBqM1hlWm96MjdLalhQaEFtaE8iLCJpYXQiOjE2NDk4MjMxNTMsImV4cCI6MTY0OTg1OTE1M30.R_zm-f2e6ZVKW73ycPXbBtoBk8gGNytiol4ET4RtNTmgTElFHNDUmyHJDTJbzyHACOju5RcR4o0kpwxdkCmZy7iQw1U4JphAhb1Na4wKHJqk7zn1wJ-hrHou7QGnuVufQTvLnxyxcF6AMc5gxi3CbQf1p5NH0JQpdgc7R-tiQDMV4sa7mWMdVVNHv7oIJFu7PKuPKkg9Aox71dtq-e5_Ucth7JNkDHV61xvJ3L6UoPk9BVDqj4pT84T_ucfKsREdS-_6_2vTneDycxl1UW7_e3UTXpvsaui87LKSBs4L2feOuWTxRL62-XKN--D02tLY6nLdu-OAFEnLy1NX8h0qqA","scope":"openid","expires_in":86400,"token_type":"Bearer"}~/src/github.com/hashicorp/xlgmokha/src/oidc [main]
+