Skip to content

Commit

Permalink
Add Support for the PLAIN authMechanism (#223)
Browse files Browse the repository at this point in the history
* Add support for LDAP authentication (#5)

* Add support for LDAP authentication

* Unit test for url parser changes

* Mention PLAIN auth support in the Readme (#6)

* Mention PLAIN auth support in the Readme

* tweak wording

* Update readme (#7)
  • Loading branch information
JD-Robertson authored Nov 6, 2023
1 parent 2823e26 commit f01d497
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 0 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,11 @@ separated in sub folders and module namespaces.
## Auth Mechanisms

For versions of Mongo 3.0 and greater, the auth mechanism defaults to SCRAM.

If connecting to MongoDB Enterprise Edition or MongoDB Atlas, the [PLAIN](https://www.mongodb.com/docs/manual/tutorial/authenticate-nativeldap-activedirectory/)
auth mechanism is supported for LDAP authentication. The GSSAPI auth mechanism used for Kerberos authentication
is not currently supported.

If you'd like to use [MONGODB-X509](https://www.mongodb.com/docs/v6.0/tutorial/configure-x509-client-authentication/)
authentication, you can specify that as a `start_link` option.

Expand Down
4 changes: 4 additions & 0 deletions lib/mongo/auth.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ defmodule Mongo.Auth do
Mongo.Auth.X509
end

defp mechanism(%{wire_version: version, auth_mechanism: :plain}) when version >= 3 do
Mongo.Auth.PLAIN
end

defp mechanism(%{wire_version: version}) when version >= 3 do
Mongo.Auth.SCRAM
end
Expand Down
31 changes: 31 additions & 0 deletions lib/mongo/auth/plain.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
defmodule Mongo.Auth.PLAIN do
@moduledoc false
alias Mongo.MongoDBConnection.Utils

def auth({nil, nil}, _db, _s) do
:ok
end

def auth({username, password}, _db, s) do
auth_payload = build_auth_payload(username, password)
message = [saslStart: 1, mechanism: "PLAIN", payload: auth_payload]

case Utils.command(-3, message, s) do
{:ok, _flags, %{"ok" => ok, "done" => true}} when ok == 1 ->
:ok

{:ok, _flags, %{"ok" => ok, "errmsg" => reason, "code" => code}} when ok == 0 ->
{:error, Mongo.Error.exception(message: "auth failed for user #{username}: #{reason}", code: code)}

error ->
error
end
end

defp build_auth_payload(username, password) do
# https://www.ietf.org/rfc/rfc4616.txt
# Null separate listed of authorization ID (blank), username, password. These are sent as raw UTF-8.
payload = "\0#{username}\0#{password}"
%BSON.Binary{binary: payload}
end
end
1 change: 1 addition & 0 deletions lib/mongo/url_parser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ defmodule Mongo.UrlParser do

defp decode_percent(:username, value), do: URI.decode_www_form(value)
defp decode_percent(:password, value), do: URI.decode_www_form(value)
defp decode_percent(:auth_source, value), do: URI.decode_www_form(value)
defp decode_percent(_other, value), do: value

defp parse_query_options(opts, %{"options" => options}) when is_binary(options) do
Expand Down
20 changes: 20 additions & 0 deletions test/mongo/url_parser_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -199,5 +199,25 @@ defmodule Mongo.UrlParserTest do
username = Keyword.get(opts, :username)
assert username == real_username
end

test "external auth source " do
encoded_external_auth_source = URI.encode_www_form("$external")
url = "mongodb://user:[email protected]:27017,seed2.domain.com:27017,seed3.domain.com:27017/db_name?replicaSet=set-name&authMechanism=PLAIN&authSource=#{encoded_external_auth_source}&tls=true"

assert UrlParser.parse_url(url: url) |> Keyword.drop([:pw_safe]) == [
password: "*****",
username: "user",
database: "db_name",
tls: true,
auth_source: "$external",
auth_mechanism: :plain,
set_name: "set-name",
seeds: [
"seed1.domain.com:27017",
"seed2.domain.com:27017",
"seed3.domain.com:27017"
]
]
end
end
end

0 comments on commit f01d497

Please sign in to comment.