Skip to content

Commit 00c65d3

Browse files
wtrockigssbznGustavo Bazan
authored
CLOUDP-282641: Addding example for saving OAuth token (#478)
Co-authored-by: Gustavo Bazan <[email protected]> Co-authored-by: Gustavo Bazan <[email protected]>
1 parent e99019c commit 00c65d3

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed

docs/doc_4_authentication.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,11 @@ revokeConfig.RevokeToken(context.Background(), &auth.Token{
9595
AccessToken: "yourTokenHere"
9696
});
9797
```
98+
### OAuth Token Cache
99+
100+
Service Account OAuth Access Tokens validity is expressed as a number of seconds in the `expires_in` field.
101+
Clients can cache these Access Tokens to mitigate rate limiting and adhere to [Access Token limits](https://www.mongodb.com/docs/manual/reference/limits/#mongodb-atlas-service-account-limits).
102+
103+
For an example on how to cache and reuse OAuth tokens in the Atlas SDK for Go, see the Service Account OAuth Token Cache
104+
[Service Account OAuth Token Cache example](https://github.com/mongodb/atlas-sdk-go/tree/main/examples/service_account_token_store).
98105

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"go.mongodb.org/atlas-sdk/v20241023002/auth"
8+
"log"
9+
"os"
10+
"strings"
11+
12+
"go.mongodb.org/atlas-sdk/v20241023002/admin"
13+
"go.mongodb.org/atlas-sdk/v20241023002/auth/clientcredentials"
14+
)
15+
16+
// Variable provided as example.
17+
var cachedToken []byte
18+
19+
// Example caching a Service Account OAuth tokens
20+
// to memory and reloading it for reuse
21+
22+
// Required env variables to run example:
23+
// export MONGODB_ATLAS_CLIENT_ID="your_client_id"
24+
// export MONGODB_ATLAS_CLIENT_SECRET="your_client_secret"
25+
func main() {
26+
host := os.Getenv("MONGODB_ATLAS_BASE_URL")
27+
28+
// Fetch clientID and clientSecret from environment variables
29+
clientID := os.Getenv("MONGODB_ATLAS_CLIENT_ID")
30+
clientSecret := os.Getenv("MONGODB_ATLAS_CLIENT_SECRET")
31+
32+
if clientID == "" || clientSecret == "" {
33+
log.Fatal("Missing required environment variables")
34+
}
35+
36+
// 1. Create instance of OAuth config
37+
conf := clientcredentials.NewConfig(clientID, clientSecret)
38+
if host != "" {
39+
conf.TokenURL = strings.Trim(host, "/") + clientcredentials.TokenAPIPath
40+
conf.RevokeURL = strings.Trim(host, "/") + clientcredentials.RevokeAPIPath
41+
}
42+
43+
// 2. Read token from storage.
44+
ctx := context.Background()
45+
src := readTokenFromDisk(ctx, conf)
46+
defer func() {
47+
if err := saveTokenToDisk(src); err != nil {
48+
log.Fatalln(err.Error())
49+
}
50+
}()
51+
sdk, err := admin.NewClient(
52+
admin.UseBaseURL(host),
53+
admin.UseDebug(true),
54+
admin.UseHTTPClient(auth.NewClient(ctx, src)),
55+
)
56+
57+
if err != nil {
58+
log.Fatalln(err.Error())
59+
}
60+
projects, _, err := sdk.ProjectsApi.ListProjects(ctx).Execute()
61+
if err != nil {
62+
log.Fatalln(err.Error())
63+
}
64+
fmt.Printf("Projects size: %d\n", projects.GetTotalCount())
65+
}
66+
67+
func saveTokenToDisk(tokenSource auth.TokenSource) error {
68+
token, err := tokenSource.Token()
69+
if err != nil {
70+
log.Fatalln(err.Error())
71+
}
72+
// Fetch OAuth Token from memory
73+
val, err := json.Marshal(token)
74+
if err != nil {
75+
return err
76+
}
77+
78+
fmt.Println("Saving token")
79+
// TODO example uses memory storage.
80+
// Please adjust method for your own use cases.
81+
// For example use WriteFile method
82+
// os.WriteFile("token", val, 0600)
83+
cachedToken = val
84+
return nil
85+
}
86+
87+
func readTokenFromDisk(ctx context.Context, conf *clientcredentials.Config) auth.TokenSource {
88+
// TODO in real cases replace with os.ReadFile("yourTokenCache")
89+
data := cachedToken // data, err := os.ReadFile("token")
90+
var token *auth.Token
91+
if data == nil {
92+
fmt.Println("No cached token detected")
93+
// No cached token return token source
94+
return conf.TokenSource(ctx)
95+
}
96+
fmt.Println("Cached token detected")
97+
if err := json.Unmarshal(data, &token); err != nil {
98+
log.Fatalln(err.Error())
99+
}
100+
return auth.ReuseTokenSource(token, conf.TokenSource(ctx))
101+
}

0 commit comments

Comments
 (0)