Handle Mongo Connection with Percent-Encoding in Go

connection() : auth error: sasl conversation error: unable to authenticate using mechanism “SCRAM-SHA-1”: (AuthenticationFailed) Authentication failed.

Problem

I was tried to connect with mongo db with simple connection with mongo-go-driver. Here the code :

package mainimport (
"context"
"fmt"
"net/url"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
)
var ctx = context.Background()func main() {
driver := "mongodb"
host := "127.0.0.1"
port := "27017"
username := "kecci"
password := "p@sword%20"
URL := url.URL{
Scheme: driver,
Host: fmt.Sprintf("%s:%s", host, port),
}
if username != "" || password != "" {
URL.User = url.UserPassword(username, password)
}
fmt.Printf("URI: %s \n", URL.String())
clientOptions := options.Client().ApplyURI(URL.String())
clientOptions.SetDirect(true)
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
fmt.Printf("error when mongo.Connect(ctx, clientOptions), %v, %v", clientOptions, err)
}
err = client.Ping(ctx, readpref.Primary())
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println("ping success")
}

Then I got Error looks like in this output:

mongodb://kecci:p%40sword%2520@127.0.0.1:27017
connection() : auth error: sasl conversation error: unable to authenticate using mechanism “SCRAM-SHA-1”: (AuthenticationFailed) Authentication failed.

My username and password is include symbolic characters. Which it’s use format or by RF3986.

MongoDB Documentation:

MongoDB Documentation for Connection String

I use package to generate URL (ofcourse with ).

Which mean, I do “Double Encode”

Let’s see how the comparison before, after, and expected format:

Before parsed to URL   : p@sword%20
After parsed to URL : p%40sword%2520
Expected parsed to URL : p%40sword%20

As you can see the symbol of parsed to . Which is it cause of the Wrong Password.

Which is it cause of the Wrong Password.

Solving

So now I should handle it with from package golang.

And here how I solve it in :

package mainimport (
"context"
"fmt"
"net/url"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
)
var ctx = context.Background()func main() {
driver := "mongodb"
host := "127.0.0.1"
port := "27017"
username, err := url.QueryUnescape("kecci")
if err != nil {
username = "kecci"
}
password, err := url.QueryUnescape("p@sword%20")
if err != nil {
password = "p@sword%20"
}
URL := url.URL{
Scheme: driver,
Host: fmt.Sprintf("%s:%s", host, port),
}
if username != "" || password != "" {
URL.User = url.UserPassword(username, password)
}
fmt.Printf("URI: %s \n", URL.String())
clientOptions := options.Client().ApplyURI(URL.String())
clientOptions.SetDirect(true)
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
fmt.Printf("error when mongo.Connect(ctx, clientOptions), %v, %v", clientOptions, err)
}
err = client.Ping(ctx, readpref.Primary())
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println("ping success")
}

output:

mongodb://kecci:p%40sword%20@127.0.0.1:27017
ping success

Conclusion

What I’m trying to do to solve it is :

  1. Try to Decode URL / Unescape Query of my password & username. If decode got an error, we re-set the username & password before.
  2. After username & password was clear without Encode URL / Percent-Encode. We proceed the to get the final format.
  3. Done. You can try connect to your mongo db with the right URI.

I also put the code on my github: https://github.com/kecci/mongo-connection-go

That’s all. Have a good day.

Thank You.

Source

Software Engineer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store