Docs Menu
Docs Home
/ /
Atlas App Services
/

Wire Protocol

On this page

  • Overview
  • Compatible Clients
  • Connection Strings
  • Credentials
  • Region
  • Parameters
  • Enable Wire Protocol Connections
  • Connect Over the Wire Protocol
  • Connect to App Services with a Connection String
  • Read and Modify Data
  • Call a Function
  • Call a Service Action [DEPRECATED]
  • Get the Logged In User's Data

Atlas App Services natively implements a subset of the MongoDB wire protocol, which allows you to connect to an App through one of its linked MongoDB Atlas data sources using standard MongoDB drivers and tools. Clients use a specialized App Services connection string to connect and send requests. App Services supports most client features over the wire protocol, including role-based data access rules, functions, and service actions.

This is a good choice for languages that do not currently have a Realm SDK. The examples here are for Python, C++11, and the Mongo Shell. Any MongoDB driver that supports the appName connection string parameter can use the wire protocol to connect to App Services.

Note

You can use the following tools and drivers to communicate with App Services using a connection string:

  • Version 4.0+ of the mongo shell.

  • Any MongoDB driver that supports the appName connection string parameter. All official MongoDB drivers support this parameter in their current releases.

Note

Connections to App Services over the wire protocol have access to the full functionality of the MongoDB Service. However, App Services does not support all operations and features available in standard tools and clients. For details, see MongoDB Service Limitations.

To connect to App Services over the wire protocol, you must construct a MongoDB connection string that includes credentials for an application user and an application-specific appName query parameter.

Important

URL Encoding

You must URL encode connection strings before you can use them to connect to App Services. Connection strings in the App Services UI are properly encoded by default.

App Services connection strings have the following form:

mongodb://<credentials>@<region>.services.cloud.mongodb.com:27020/?<parameters>

All operations that you issue over the wire protocol run in the context of a specific application user that you specify in the connection string. The user must be registered with one of the following authentication providers:

The contents of connection string credentials depend on the authentication provider with which the user registered:

Format
<email>:<password>
Fields
<email>
The user's registered email address.
<password>
The user's password.
Example
joe.mango@company.com:SuperSecretPassword123
Format
_:<apiKey>
Fields
<apiKey>
An active application API Key.
Example
_:tOSJwYhLLam1qTAwP8rZ5M9BiHfn69w5xrya52dYeOv1PdTlD68i8gKOaN0Wy24z
Format
_:<customAuthToken>
Fields
<customAuthToken>
A custom authentication JSON Web Token.
Example
_:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

The connection string must specify the deployment region and cloud provider in which the App is hosted.

Global Apps use the global region:

mongodb://<credentials>@global.services.cloud.mongodb.com:27020/?<parameters>

Local Apps specify the cloud provider and region name using <region>.<cloud> format. For example, an app deployed to aws-us-east-1 would use the following connection string:

mongodb://<credentials>@us-east-1.aws.services.cloud.mongodb.com:27020/?<parameters>

App Services requires specific connection string options that identify the application you want to connect to and the authentication provider associated with the credentials that you provide.

App Services connection strings have the following query parameters:

Parameter
Description
authMechanism
This parameter should always be set to PLAIN.
authSource
This parameter should always be set to $external.
appName

Uniquely identifies the application, MongoDB service, and authentication provider to which you want to connect.

The appName parameter has the following form:

<app id>:<service>:<provider>
<app id>
The App ID of the App.
<service>
The name of the MongoDB Service that you want to connect to. This value will always be mongodb-atlas.
<provider>

The authentication provider for which you provided credentials.

Valid values:

  • local-userpass

  • api-key

  • custom-token

You must enable wire protocol connections for a linked clusters before you can connect to an App Services App with a connection string.

1

In the Manage section of the left navigation menu, click Linked Data Sources.

In the list of data sources, select the cluster on which you want to enable wire protocol connections.

2

Set the toggle for MongoDB Connection String to Enabled. In the Authentication Method section that appears, choose and configure how you want to authenticate the wire protocol connections.

The enable wire protocol toggle in the UI
3
1

To enable MongoDB wire protocol connections with the App Services CLI, you need a local copy of your application's configuration files.

To pull a local copy of the latest version of your app, run the following:

appservices pull --remote="<Your App ID>"

Tip

You can also download a copy of your application's configuration files from the Deploy > Export App screen in the App Services UI.

2

To enable wire protocol connections for a linked cluster, open the cluster's config.json file and set the value of config.wireProtocolEnabled to true:

{
"name": "mongodb-atlas",
"type": "mongodb-atlas",
"config": {
"wireProtocolEnabled": true,
...
}
}
3

Once you've enabled wire protocol connections for the cluster in config.json, you can push the config to your remote app. App Services CLI immediately deploys the update on push.

appservices push --remote="<Your App ID>"

To connect to App Services over the wire protocol, pass a URL-encoded App Services connection string when you create a client, just as you would with a regular connection string.

$ mongo "mongodb://<user>:<password>@services.cloud.mongodb.com:27020/?authMechanism=PLAIN&authSource=%24external&ssl=true&appName=realm-application-abcde:mongodb-atlas:local-userpass"
mongocxx::instance instance{};
mongocxx::uri uri("mongodb://<user>:<password>@services.cloud.mongodb.com:27020/?authMechanism=PLAIN&authSource=%24external&ssl=true&appName=realm-application-abcde:mongodb-atlas:local-userpass");
mongocxx::client client(uri);
client = pymongo.MongoClient("mongodb://<user>:<password>@services.cloud.mongodb.com:27020/?authMechanism=PLAIN&authSource=%24external&ssl=true&appName=realm-application-abcde:mongodb-atlas:local-userpass")

While connected to App Services over the wire protocol you can use standard MongoDB CRUD operations. App Services applies role-based data access rules to all queries in the context of the authenticated user specified in the connection string credentials.

> use HR
> db.employees.findOne();
{
"_id": ObjectId("5ae782e48f25b9dc5c51c4a5"),
"employeeId": 854271626,
"name": {
"first": "Lucas",
"last": "Lewis"
},
"role": "PM",
"salary": 200000,
"email": "Lucas.Lewis.0271@company.com",
"password": "<password>",
"manager": {
"id": 328892725,
"email": "Daniel.Wilson.0474@company.com",
"name": {
"first": "Daniel",
"last": "Wilson"
}
}
}
mongocxx::database db = client["HR"];
mongocxx::collection employees = db["employees"];
bsoncxx::stdx::optional<bsoncxx::document::value> result =
collection.find_one({});
if(result) {
std::cout << bsoncxx::to_json(result) << "\n";
}
>>> db = client["HR"]
>>> employee = db["employees"].find_one();
>>> pprint(employee)
{'_id': ObjectId('5ae782e48f25b9dc5c51c4a5'),
'email': 'Lucas.Lewis.0271@company.com',
'employeeId': 854271626.0,
'manager': {'email': 'Daniel.Wilson.0474@company.com',
'id': 328892725.0,
'name': {'first': 'Daniel', 'last': 'Wilson'}},
'name': {'first': 'Lucas', 'last': 'Lewis'},
'password': '<password>',
'role': 'PM',
'salary': 200000}

You can call functions using the callFunction database command.

Command
Description
Prototype
callFunction
Calls the specified function and returns any result.
{
callFunction: <function name>,
arguments: [<arg1>, <arg2>, ...]
}
> db.runCommand({
... callFunction: "getEmployeeById",
... arguments: ["5ae782e48f25b9dc5c51c4a5"]
...});
{
"ok" : 1,
"response" : {
"_id": ObjectId("5ae782e48f25b9dc5c51c4a5"),
"employeeId": 854271626,
"name": {
"first": "Lucas",
"last": "Lewis"
},
"role": "PM",
"salary": 200000,
"email": "Lucas.Lewis.0271@company.com",
"password": "<password>",
"manager": {
"id": 328892725,
"email": "Daniel.Wilson.0474@company.com",
"name": {
"first": "Daniel",
"last": "Wilson"
}
}
}
}
db.runCommand({
callFunction: "getEmployeeById",
arguments: ["5ae782e48f25b9dc5c51c4a5"]
});
>>> function_result = db.command("callFunction", "getEmployeeById",
... arguments=["5ae782e48f25b9dc5c51c4a5"]
...)
>>> pprint.pprint(function_result)
{'ok': 1,
'response': {'_id': ObjectId('5ae782e48f25b9dc5c51c4a5'),
'email': 'Lucas.Lewis.0271@company.com',
'employeeId': 854271626.0,
'manager': {'email': 'Daniel.Wilson.0474@company.com',
'id': 328892725.0,
'name': {'first': 'Daniel', 'last': 'Wilson'}},
'name': {'first': 'Lucas', 'last': 'Lewis'},
'password': '<password>',
'role': 'PM',
'salary': 200000}}

You can call service actions using the callServiceFunction database command.

Command
Description
Prototype
callServiceFunction
Calls the specified service action and returns any result.
{
callServiceFunction: <function name>,
service: <service name>,
arguments: [<arg1>, <arg2>, ...]
}
> db.runCommand({
... callServiceFunction: "get",
... service: "http",
... arguments: [{ url: "https://jsonplaceholder.typicode.com/todos/1" }]
... });
{
"ok" : 1,
"response" : {
"status" : "200 OK",
"statusCode" : 200,
"contentLength" : NumberLong(-1),
"headers" : {
"Content-Type" : ["application/json; charset=utf-8"],
"Connection" : ["keep-alive"],
"Vary" : ["Origin, Accept-Encoding"],
"X-Content-Type-Options" : ["nosniff"],
"Via" : ["1.1 vegur"],
"X-Powered-By" : ["Express"],
"Cf-Cache-Status" : ["HIT"],
"Expect-Ct" : ["max-age=604800, report-uri=\"https://example.com/cdn-cgi/beacon/expect-ct\""],
"Set-Cookie" : ["__cfduid=d7f650e765d41beb7598ce2ab62d0c0191536867096; expires=Fri, 13-Sep-19 19:31:36 GMT; path=/; domain=.typicode.com; HttpOnly"],
"Access-Control-Allow-Credentials" : ["true"],
"Cache-Control" : ["public, max-age=14400"],
"Pragma" : ["no-cache"],
"Etag" : ["W/\"53-hfEnumeNh6YirfjyjaujcOPPT+s\""],
"Server" : ["example.com"],
"Cf-Ray" : ["459d08f88e1e56db-IAD"],
"Date" : ["Thu, 13 Sep 2018 19:31:36 GMT"],
"Expires" : ["Thu, 13 Sep 2018 23:31:36 GMT"]
},
"cookies" : {
"__cfduid" : {
"value" : "d7f650e765d41beb7598ce2ab62d0c0191536867096",
"path" : "/",
"domain" : ".typicode.com",
"expires" : "Mon, 01 Jan 0001 00:00:00 GMT",
"maxAge" : 0,
"secure" : false,
"httpOnly" : true
}
},
"body" : BinData(0,"ewogICJ1c2VySWQiOiAxLAogICJpZCI6IDEsCiAgInRpdGxlIjogImRlbGVjdHVzIGF1dCBhdXRlbSIsCiAgImNvbXBsZXRlZCI6IGZhbHNlCn0=")
}
}
db.runCommand({
callServiceFunction: "get",
service: "http",
arguments: [{ url: "https://jsonplaceholder.typicode.com/todos/1" }]
});
>>> result = db.command("callServiceFunction", "get",
... service="http",
... arguments=[{"url": "https://jsonplaceholder.typicode.com/todos/1"}]
...)
>>> pprint.pprint(result)
{'ok': 1,
'response': {'body': b'{\n "userId": 1,\n "id": 1,\n "title": "delectus aut'
b' autem",\n "completed": false\n}',
'contentLength': -1,
'cookies': {'__cfduid': {'domain': '.typicode.com',
'expires': 'Mon, 01 Jan 0001 00:00:00 '
'GMT',
'httpOnly': True,
'maxAge': 0,
'path': '/',
'secure': False,
'value': 'd4b10004e96ca7fee0be03dceebaf2ab71536866400'}},
'headers': {'Access-Control-Allow-Credentials': ['true'],
'Cache-Control': ['public, max-age=14400'],
'Cf-Cache-Status': ['HIT'],
'Cf-Ray': ['459cf7fc7e20c1bd-IAD'],
'Connection': ['keep-alive'],
'Content-Type': ['application/json; charset=utf-8'],
'Date': ['Thu, 13 Sep 2018 19:20:00 GMT'],
'Etag': ['W/"53-hfEnumeNh6YirfjyjaujcOPPT+s"'],
'Expect-Ct': ['max-age=604800, '
'report-uri="https://example.com/cdn-cgi/beacon/expect-ct"'],
'Expires': ['Thu, 13 Sep 2018 23:20:00 GMT'],
'Pragma': ['no-cache'],
'Server': ['example.com'],
'Set-Cookie': ['__cfduid=d4b10004e96ca7fee0be03dceebaf2ab71536866400; '
'expires=Fri, 13-Sep-19 19:20:00 GMT; '
'path=/; domain=.typicode.com; '
'HttpOnly'],
'Vary': ['Origin, Accept-Encoding'],
'Via': ['1.1 vegur'],
'X-Content-Type-Options': ['nosniff'],
'X-Powered-By': ['Express']},
'status': '200 OK',
'statusCode': 200}}

You can get the user object for the authenticated user using the userProfile database command.

Command
Description
Prototype
userProfile
Returns the user object for the authenticated user.
{
userProfile: 1
}
> db.runCommand({ userProfile: 1 });
{
"ok" : 1,
"profile" : {
"userid" : "5ad7a79e8f25b975898d77b8",
"domainid" : ObjectId("5ad7a69746224c054067c8b1"),
"identities" : [
{
}
],
"data" : "{\"email\":\"joe.mango@company.com\"}",
"type" : "normal",
"roleassignments" : [ ]
}
}
db.runCommand({ userProfile: 1 });
>>> result = db.command("userProfile", 1)
>>> pprint.pprint(result)
{'ok': 1,
'profile': {'data': '{"email":"joe.mango@company.com"}',
'domainid': ObjectId('5ad7a69746224c054067c8b1'),
'identities': [{}],
'roleassignments': [],
'type': 'normal',
'userid': '5ad7a79e8f25b975898d77b8'}}

Back

Read Preference