1
2
3
4
5
6
7 package auth_test
8
9 import (
10 "context"
11 "strings"
12 "testing"
13
14 "encoding/base64"
15
16 "go.mongodb.org/mongo-driver/internal/require"
17 "go.mongodb.org/mongo-driver/mongo/description"
18 "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
19 . "go.mongodb.org/mongo-driver/x/mongo/driver/auth"
20 "go.mongodb.org/mongo-driver/x/mongo/driver/drivertest"
21 )
22
23 func TestPlainAuthenticator_Fails(t *testing.T) {
24 t.Parallel()
25
26 authenticator := PlainAuthenticator{
27 Username: "user",
28 Password: "pencil",
29 }
30
31 resps := make(chan []byte, 1)
32 writeReplies(resps, bsoncore.BuildDocumentFromElements(nil,
33 bsoncore.AppendInt32Element(nil, "ok", 1),
34 bsoncore.AppendInt32Element(nil, "conversationId", 1),
35 bsoncore.AppendBinaryElement(nil, "payload", 0x00, []byte{}),
36 bsoncore.AppendInt32Element(nil, "code", 143),
37 bsoncore.AppendBooleanElement(nil, "done", true),
38 ))
39
40 desc := description.Server{
41 WireVersion: &description.VersionRange{
42 Max: 6,
43 },
44 }
45 c := &drivertest.ChannelConn{
46 Written: make(chan []byte, 1),
47 ReadResp: resps,
48 Desc: desc,
49 }
50
51 err := authenticator.Auth(context.Background(), &Config{Description: desc, Connection: c})
52 if err == nil {
53 t.Fatalf("expected an error but got none")
54 }
55
56 errPrefix := "unable to authenticate using mechanism \"PLAIN\""
57 if !strings.HasPrefix(err.Error(), errPrefix) {
58 t.Fatalf("expected an err starting with \"%s\" but got \"%s\"", errPrefix, err)
59 }
60 }
61
62 func TestPlainAuthenticator_Extra_server_message(t *testing.T) {
63 t.Parallel()
64
65 authenticator := PlainAuthenticator{
66 Username: "user",
67 Password: "pencil",
68 }
69
70 resps := make(chan []byte, 2)
71 writeReplies(resps, bsoncore.BuildDocumentFromElements(nil,
72 bsoncore.AppendInt32Element(nil, "ok", 1),
73 bsoncore.AppendInt32Element(nil, "conversationId", 1),
74 bsoncore.AppendBinaryElement(nil, "payload", 0x00, []byte{}),
75 bsoncore.AppendBooleanElement(nil, "done", false),
76 ), bsoncore.BuildDocumentFromElements(nil,
77 bsoncore.AppendInt32Element(nil, "ok", 1),
78 bsoncore.AppendInt32Element(nil, "conversationId", 1),
79 bsoncore.AppendBinaryElement(nil, "payload", 0x00, []byte{}),
80 bsoncore.AppendBooleanElement(nil, "done", true),
81 ))
82
83 desc := description.Server{
84 WireVersion: &description.VersionRange{
85 Max: 6,
86 },
87 }
88 c := &drivertest.ChannelConn{
89 Written: make(chan []byte, 1),
90 ReadResp: resps,
91 Desc: desc,
92 }
93
94 err := authenticator.Auth(context.Background(), &Config{Description: desc, Connection: c})
95 if err == nil {
96 t.Fatalf("expected an error but got none")
97 }
98
99 errPrefix := "unable to authenticate using mechanism \"PLAIN\": unexpected server challenge"
100 if !strings.HasPrefix(err.Error(), errPrefix) {
101 t.Fatalf("expected an err starting with \"%s\" but got \"%s\"", errPrefix, err)
102 }
103 }
104
105 func TestPlainAuthenticator_Succeeds(t *testing.T) {
106 t.Parallel()
107
108 authenticator := PlainAuthenticator{
109 Username: "user",
110 Password: "pencil",
111 }
112
113 resps := make(chan []byte, 1)
114 writeReplies(resps, bsoncore.BuildDocumentFromElements(nil,
115 bsoncore.AppendInt32Element(nil, "ok", 1),
116 bsoncore.AppendInt32Element(nil, "conversationId", 1),
117 bsoncore.AppendBinaryElement(nil, "payload", 0x00, []byte{}),
118 bsoncore.AppendBooleanElement(nil, "done", true),
119 ))
120
121 desc := description.Server{
122 WireVersion: &description.VersionRange{
123 Max: 6,
124 },
125 }
126 c := &drivertest.ChannelConn{
127 Written: make(chan []byte, 1),
128 ReadResp: resps,
129 Desc: desc,
130 }
131
132 err := authenticator.Auth(context.Background(), &Config{Description: desc, Connection: c})
133 if err != nil {
134 t.Fatalf("expected no error but got \"%s\"", err)
135 }
136
137 if len(c.Written) != 1 {
138 t.Fatalf("expected 1 messages to be sent but had %d", len(c.Written))
139 }
140
141 payload, _ := base64.StdEncoding.DecodeString("AHVzZXIAcGVuY2ls")
142 expectedCmd := bsoncore.BuildDocumentFromElements(nil,
143 bsoncore.AppendInt32Element(nil, "saslStart", 1),
144 bsoncore.AppendStringElement(nil, "mechanism", "PLAIN"),
145 bsoncore.AppendBinaryElement(nil, "payload", 0x00, payload),
146 )
147 compareResponses(t, <-c.Written, expectedCmd, "$external")
148 }
149
150 func TestPlainAuthenticator_SucceedsBoolean(t *testing.T) {
151 t.Parallel()
152
153 authenticator := PlainAuthenticator{
154 Username: "user",
155 Password: "pencil",
156 }
157
158 resps := make(chan []byte, 1)
159 writeReplies(resps, bsoncore.BuildDocumentFromElements(nil,
160 bsoncore.AppendBooleanElement(nil, "ok", true),
161 bsoncore.AppendInt32Element(nil, "conversationId", 1),
162 bsoncore.AppendBinaryElement(nil, "payload", 0x00, []byte{}),
163 bsoncore.AppendBooleanElement(nil, "done", true),
164 ))
165
166 desc := description.Server{
167 WireVersion: &description.VersionRange{
168 Max: 6,
169 },
170 }
171 c := &drivertest.ChannelConn{
172 Written: make(chan []byte, 1),
173 ReadResp: resps,
174 Desc: desc,
175 }
176
177 err := authenticator.Auth(context.Background(), &Config{Description: desc, Connection: c})
178 require.NoError(t, err, "Auth error")
179 require.Len(t, c.Written, 1, "expected 1 messages to be sent")
180
181 payload, err := base64.StdEncoding.DecodeString("AHVzZXIAcGVuY2ls")
182 require.NoError(t, err, "DecodeString error")
183
184 expectedCmd := bsoncore.BuildDocumentFromElements(nil,
185 bsoncore.AppendInt32Element(nil, "saslStart", 1),
186 bsoncore.AppendStringElement(nil, "mechanism", "PLAIN"),
187 bsoncore.AppendBinaryElement(nil, "payload", 0x00, payload),
188 )
189 compareResponses(t, <-c.Written, expectedCmd, "$external")
190 }
191
View as plain text