...
1
2
3
4
5
6
7 package auth
8
9 import (
10 "context"
11 "fmt"
12 "io"
13
14
15
16
17 "crypto/md5"
18
19 "go.mongodb.org/mongo-driver/bson"
20 "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
21 "go.mongodb.org/mongo-driver/x/mongo/driver"
22 "go.mongodb.org/mongo-driver/x/mongo/driver/operation"
23 )
24
25
26
27
28
29 const MONGODBCR = "MONGODB-CR"
30
31 func newMongoDBCRAuthenticator(cred *Cred) (Authenticator, error) {
32 return &MongoDBCRAuthenticator{
33 DB: cred.Source,
34 Username: cred.Username,
35 Password: cred.Password,
36 }, nil
37 }
38
39
40
41
42
43 type MongoDBCRAuthenticator struct {
44 DB string
45 Username string
46 Password string
47 }
48
49
50
51
52
53 func (a *MongoDBCRAuthenticator) Auth(ctx context.Context, cfg *Config) error {
54
55 db := a.DB
56 if db == "" {
57 db = defaultAuthDB
58 }
59
60 doc := bsoncore.BuildDocumentFromElements(nil, bsoncore.AppendInt32Element(nil, "getnonce", 1))
61 cmd := operation.NewCommand(doc).
62 Database(db).
63 Deployment(driver.SingleConnectionDeployment{cfg.Connection}).
64 ClusterClock(cfg.ClusterClock).
65 ServerAPI(cfg.ServerAPI)
66 err := cmd.Execute(ctx)
67 if err != nil {
68 return newError(err, MONGODBCR)
69 }
70 rdr := cmd.Result()
71
72 var getNonceResult struct {
73 Nonce string `bson:"nonce"`
74 }
75
76 err = bson.Unmarshal(rdr, &getNonceResult)
77 if err != nil {
78 return newAuthError("unmarshal error", err)
79 }
80
81 doc = bsoncore.BuildDocumentFromElements(nil,
82 bsoncore.AppendInt32Element(nil, "authenticate", 1),
83 bsoncore.AppendStringElement(nil, "user", a.Username),
84 bsoncore.AppendStringElement(nil, "nonce", getNonceResult.Nonce),
85 bsoncore.AppendStringElement(nil, "key", a.createKey(getNonceResult.Nonce)),
86 )
87 cmd = operation.NewCommand(doc).
88 Database(db).
89 Deployment(driver.SingleConnectionDeployment{cfg.Connection}).
90 ClusterClock(cfg.ClusterClock).
91 ServerAPI(cfg.ServerAPI)
92 err = cmd.Execute(ctx)
93 if err != nil {
94 return newError(err, MONGODBCR)
95 }
96
97 return nil
98 }
99
100 func (a *MongoDBCRAuthenticator) createKey(nonce string) string {
101
102
103
104 h := md5.New()
105
106 _, _ = io.WriteString(h, nonce)
107 _, _ = io.WriteString(h, a.Username)
108 _, _ = io.WriteString(h, mongoPasswordDigest(a.Username, a.Password))
109 return fmt.Sprintf("%x", h.Sum(nil))
110 }
111
View as plain text