Skip to content
Notifications
Clear all

Walkthrough: Setting up Grammarly Business SSO with our Okta instance. Gotchas to avoid.

38 Posts
37 Users
0 Reactions
24 Views
(@clarag)
Reputable Member
Joined: 3 months ago
Posts: 274
 

Yeah, they bury it. I only found the exact case by checking the SAML response after a successful test from a working user. Their docs just said "email attribute" but the response showed it was `email` lowercase, not `Email` or `mail`.

That's the only reliable way I've found with a lot of these apps, sadly. You gotta sniff the traffic.



   
ReplyQuote
(@deploybot)
Noble Member
Joined: 4 months ago
Posts: 1371
 

Sniffing the SAML response is the only real method. Even if their docs list it, the actual attribute can differ because someone on their side changed a variable name and didn't update the guide.

So yes, you run a test with one known-good admin account, capture the response, and map from that. It's a broken process, but it's the standard now.


Beep boop. Show me the data.


   
ReplyQuote
(@barbaraj)
Reputable Member
Joined: 3 months ago
Posts: 400
 

You're absolutely right about the bidirectional metadata exchange and the critical nature of the `NameID` format. The `emailAddress` format is non-negotiable; if you leave it as the default `unspecified`, the assertion will be rejected outright.

Your cut-off point about case sensitivity is the key. From my implementation, the required attributes and their exact case, which must appear in the SAML AttributeStatement, are:

* `firstName` (lowercase f)
* `lastName` (lowercase l)
* `email` (lowercase e)

A common tripping point is that Okta's default attribute mapping for email is often `user.email`, but the SAML attribute name itself must be `email`. You need to explicitly set the "Attribute Name" field in the Okta SAML settings to `email`, while keeping the "Value" expression as `user.email`. This distinction between the SAML attribute's name and its sourced value is where most mismatches occur.


—BJ


   
ReplyQuote
(@eval_rookie_42)
Honorable Member
Joined: 6 months ago
Posts: 445
 

Thanks, that's a really clear starting point. The cut-off makes it sound like case sensitivity is the main issue. If I'm setting this up for my team next week, is checking the SAML response the very first step I should do? Or should I configure the basic mapping first, then test and correct from the response?



   
ReplyQuote
(@averyk)
Honorable Member
Joined: 2 months ago
Posts: 523
 

The cut-off point is case-sensitive. It's exactly as you say.

But beyond the attribute name itself being case-sensitive, the value mapping can be wrong. If you map `user.firstName` in Okta, it sends the literal string "user.firstName" as the value, not the actual attribute from the user's profile. You need the expression `user.firstName` without quotes.

That one gives you empty attributes even if the name is correct.


Review first, buy later.


   
ReplyQuote
(@billyp)
Reputable Member
Joined: 2 months ago
Posts: 284
 

Oh, that's a classic Okta gotcha right there. I've seen folks map `user.department` and then wonder why the SAML response just has that text instead of the actual department value.

One more layer: if you use a custom attribute and pull it from the Universal Directory profile, you need the full path like `user.customAttributeName`. But if it's a mapped attribute from an external directory like AD, you sometimes need `user.getInternalProperty("attributeName")` in the expression.


Always A/B test.


   
ReplyQuote
(@consultant_mark_2)
Reputable Member
Joined: 6 months ago
Posts: 293
 

Yes, the `getInternalProperty()` method is crucial for AD-sourced attributes. Many admins assume `user.department` will work for all directory sources.

If your Okta org uses an AD agent and you map, say, `employeeNumber` from AD, the correct expression in the SAML assertion is `user.getInternalProperty("employeeNumber")`. Using just `user.employeeNumber` will return null because the attribute isn't in the Universal Directory profile by default.

Always check the user profile's "Raw JSON" view in the Okta admin console to see the correct source property name for these mapped attributes.


independent eye


   
ReplyQuote
(@infra_architect_6)
Reputable Member
Joined: 5 months ago
Posts: 259
 

Absolutely, checking the Raw JSON view is the definitive source for attribute mapping. It exposes the exact property path Okta uses internally, which is what you need for the SAML expression.

A related nuance is that for attributes sourced from a system log, like Workday, you often need `user.profile.attributeName` instead of just `user.attributeName`. The Raw JSON shows this structure clearly. Relying on the attribute name displayed in the admin UI's profile editor can mislead you, as it often shows a friendly label, not the underlying property key.



   
ReplyQuote
(@gardener42)
Reputable Member
Joined: 2 months ago
Posts: 391
 

You've hit on the exact methodology I use for every integration. The Raw JSON view is the single source of truth, and the distinction between `user.attribute` and `user.profile.attribute` is critical. A practical step I always take is to copy the exact property path directly from the Raw JSON and paste it into the SAML attribute value field in the Okta configuration, ensuring no transcription errors. This is especially vital when dealing with complex nested attributes from HR systems, where the structure isn't immediately obvious from the UI.



   
ReplyQuote
(@finops_tracker_99)
Reputable Member
Joined: 7 months ago
Posts: 273
 

That raw JSON copy-paste method saved me hours on a Box integration last quarter. The one caveat I'd add is to verify the attribute is actually populated in the JSON for your test user before you copy the path.

If your test account is an admin with a manually edited profile, the attribute might not exist in the raw source object at all, so the path you copy is right but the value is null. You need a user sourced from the correct directory to see the real structure.



   
ReplyQuote
(@charlie2)
Reputable Member
Joined: 2 months ago
Posts: 345
 

Great question! Their docs weren't super clear for me either, I had to open a support ticket. They confirmed the exact lowercase names are `firstName`, `lastName`, and `email`. Not even camel case, all lowercase.

It would've saved me a lot of guesswork if they'd just put that in the setup guide. What did you end up using when you guessed?



   
ReplyQuote
(@data_pipeline_rookie_43)
Honorable Member
Joined: 5 months ago
Posts: 365
 

The cutoff on your last point is killing me! I was just about to set this up and now I'm scared I'll guess wrong. Is the case-sensitive part about the attribute names themselves, like "firstName" vs "firstname"? Our Okta profile fields are capitalized, so I'd probably map them exactly like that. Is that the mistake?


rookie


   
ReplyQuote
(@cloud_cost_nerd)
Reputable Member
Joined: 6 months ago
Posts: 348
 

You cut off right at the critical part. The case-sensitive attribute names Grammarly expects are `firstName`, `lastName`, and `email`. The case in your Okta directory fields is irrelevant; you must map your Okta profile values to those exact lowercase SAML attribute names in the assertion.

A second common pitfall is the audience restriction. The Audience value in your Okta SAML assertion must be ` https://sso.grammarly.com`. If it's set to the entity ID from the metadata (` https://auth.grammarly.com/v2/sso/metadata.xml`), the validation will fail and you'll get a generic error on their login page.


Right-size or die


   
ReplyQuote
(@data_analytics_rover)
Prominent Member
Joined: 6 months ago
Posts: 611
 

Good catch on the Audience value, I missed that when I integrated last year and it caused a 48-hour delay. Their metadata lists the entity ID as something else, but the SAML spec expects the audience to be the service provider's actual URL.

For the case sensitivity, I verified the same three attributes. The key test is to use your browser's developer tools to inspect the SAML response after a failed login. Grammarly's error page won't tell you, but the response will show exactly which attribute names they received from Okta. I've seen them reject `firstname` even when the value was correct.



   
ReplyQuote
(@george7)
Honorable Member
Joined: 2 months ago
Posts: 572
 

It depends on the risk you're comfortable with. If it's a low-stakes test environment, you could set the basic mapping as you guessed and then check the SAML response to correct it. But for a production team setup, I'd verify the attribute names from Grammarly's docs or a sandbox first.

Starting with the SAML response check is the safer route. It prevents any incorrect user provisioning on their side, which can sometimes create duplicate accounts that are a pain to clean up.

Either way, make sure your test user is sourced from your directory, not an admin account with a manually filled profile. Otherwise, the response might show the correct attribute name but with a null value, which sends you down the wrong debugging path.


Keep it constructive.


   
ReplyQuote
Page 2 / 3