Trusted Authentication
Trusted authentication is an optional extra layer of security for connecting to Grammarly. It helps prevent bad actors from impersonating your application and using your credentials to gain access to any SDK features that you may be paying for as part of your planopen in new window. It also allows you to control access to the Grammarly Text Editor Plugin on a per-user level.
How it works
Trusted authentication is based on OAuth 2.0 client authentication assertions (RFC 7523open in new window). It requires your application to have an assertion before it can connect to Grammarly. These assertions are vended by your servers and prove that the application is authorized.

For the assertions, trusted authentication uses JSON Web Tokensopen in new window (JWTs), which are signed with a private key and validated with the corresponding public key.
The SDK will automatically request assertions and use them to obtain access tokens for Grammarly’s services. The only parts of this flow you need to handle are writing an assertion endpoint that returns signed JWTs, and setting the oauthAssertionProvider
EditorConfig property to call that endpoint. We’ll walk you through how to do this in the following steps.
Step 1: Generate a public/private key pair for your app
The first step to implementing trusted authentication is to generate a public/private key pair for your app:
- Open the App Console by selecting your application from My Appsopen in new window.
- Select Trusted Authentication in the left menu.
- Click Generate new key.
- A pop-up will appear showing your private key in JSON Web Key (JWK) format. Copy and store it securely.
- Click Done.
You can now see the key ID and the date that it was created. Grammarly stores the public key but does not store your private key. If you lose it, you can generate a new public/private key pair using the instructions above.
Note that your key may not be usable for several minutes while our system updates.
WARNING
Don’t turn on "Require trusted authentication" until you complete steps 2, 3, and 4 below.
Step 2: Create an assertion endpoint that serves signed JWTs
The next step is to create an endpoint that serves assertions: JWTs signed with your private key. In order to be valid, the JWTs must follow certain requirements, which are described in this section. We provide sample assertion endpoints in a few languages as a starting point.
Note that depending on your use case, you may want to set up additional authentication logic as part of your endpoint. For instance, you can decide to only provide assertions to certain users or groups of users (e.g., only logged in users). Want help setting up more advanced assertion logic? Let us know!open in new window.
Examples
While the implementation details for the assertion endpoint will vary based on your tech stack, here are examples to help you get started:
JWT requirements
For your reference, the complete requirements for a JWT to be considered valid by Grammarly are described below.
JWT header
The following parameters are required in your JWT header:
Name | Value |
---|---|
alg | The algorithm of your private key (e.g. RS256 ), specified in the JSON for your key |
ver | v1 |
kid | The key ID of your private key |
JWT payload
The following parameters are required in your JWT payload:
Name | Value |
---|---|
sub | Your client ID |
iss | Again, your client ID |
iat | Issued time in seconds since the Unix epoch |
exp | Expiration time in seconds since the Unix epoch |
aud | https://tokens.grammarly.com/oauth2/token |
Note that the "validity window" of the assertion, defined as the time between the iat
and exp
fields, cannot be greater than 5 minutes. To account for possible clock skew, you might want to backdate your iat
by a few seconds (e.g. 5 seconds).
JWT signing
Lastly, your JWT must be properly signed with your private key.
Using the JOSEopen in new window library in a Node.js server, here’s a basic assertion generation example (this example includes iat
backdating by 5 seconds):
const now = Math.floor(new Date().getTime() / 1000); // Epoch time in seconds
const issuedAt = now - 5; // Backdate by 5 seconds to account for any clock skew
const expirationTime = issuedAt + 5 * 60; // Assertion will be valid for 5 minutes from the issuedAt
const assertion = await new jose.SignJWT({})
.setProtectedHeader({ alg: "YOUR_KEY_ALGORITHM", ver: "v1", kid: "YOUR_KEY_ID" })
.setSubject("YOUR_CLIENT_ID")
.setIssuedAt(issuedAt)
.setIssuer("YOUR_CLIENT_ID")
.setAudience("https://tokens.grammarly.com/oauth2/token")
.setExpirationTime(expirationTime)
.sign(privateKey);
You’ll find other examples of generating assertions in the sample endpoints.
Step 3: Update your application code
Now that you’ve created your assertion endpoint, you need to update your application code so that the Text Editor SDK can start using it.
The SDK uses the oauthAssertionProvider
EditorConfig property to retrieve an assertion for accessing Grammarly’s servers. As the simplest approach, you can set this property to the URL for your assertion endpoint.
<grammarly-editor-plugin client-id="YOUR_CLIENT_ID" config.oauthAssertionProvider="YOUR_SERVER_URL">
<textarea></textarea>
</grammarly-editor-plugin>
TIP
Your assertion endpoint must include the client ID in the signed JWT. Common options for getting the client ID are storing the client ID in your endpoint code or passing it to your endpoint as a query parameter (e.g. config.oauthAssertionProvider="YOUR_SERVER_URL?clientId=YOUR_CLIENT_ID"
).
Your server will need to be able to receive an HTTP GET request at this URL and return an HTTP 200 application/json
message with the following shape:
{
assertion: "YOUR_SIGNED_JWT";
}
You may need to do something more advanced with your request—like send it as an HTTP POST with special headers or modify its return type (from XML or raw text). In this case, instead of setting the oauthAssertionProvider
property to your assertion endpoint’s URL, you can set it to a function. This function should return a promise that resolves to a JSON object:
<grammarly-editor-plugin client-id="YOUR_CLIENT_ID">
<textarea></textarea>
</grammarly-editor-plugin>
document.querySelectorAll("grammarly-editor-plugin").forEach((grammarlyEditor) => {
grammarlyEditor.config = {
oauthAssertionProvider: async () => {
// Call your endpoint to get an assertion
const response = await fetch("YOUR_SERVER_URL", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
clientId: "YOUR_CLIENT_ID",
}),
});
// Handle errors
if (!response.ok) {
throw new Error("Error creating assertion");
}
// Return generated assertion
return await response.json();
},
};
});
For a working example of how to set the oauthAssertionProvider
to a custom function, see the CodeSandbox demoopen in new window. You’ll need a working assertion endpoint that accepts POST requests to test this example. The sample assertion endpoints we provide accept GET requests, but you can modify the code to accept POST requests.
Step 4: Test
We recommend testing the oauthAssertionProvider
property with a small set of users at first while "Require trusted authentication" is off for your app. Don't worry, you can still send assertions to Grammarly while "Require trusted authentication" is off.
If there is any problem with the assertion returned by your assertion endpoint (even if trusted authentication isn’t required), the connection to Grammarly will be refused. The Grammarly button will show that Grammarly is not available, and you can find further error details in the Network tab of your browser’s developer toolsopen in new window.
Note that if your app has multiple clients, you should test that assertions work for each client and client ID. Once you turn on "Require trusted authentication" for your app, it will be required for all your app’s clients.
When you’re sure that everything is working properly and the Grammarly Text Editor plugin is successfully loading in your app, you can roll out the oauthAssertionProvider
property to all your users.
Step 5: Turn on “Require trusted authentication” for your app
Once you’re confident that assertions are working properly for all your users, you’re ready to turn on "Require trusted authentication":
- Open the App Console by selecting your application from My Appsopen in new window.
- Select Trusted Authentication in the left menu.
- At the bottom of the screen, switch Require trusted authentication to ON.
- A pop-up will appear asking you to confirm your choice.
Note it may be several minutes before this change takes effect.
When trusted authentication is required, Grammarly will require a valid assertion for any connection made by any client of your app.