Md. Alim Ul Karim
Md. Alim Ul Karim

Reputation: 2432

Outlook Exchange Office 365: How to get email address from access token?

Currently, I am following this article https://dev.outlook.com/restapi/tutorial/dotnet . Everything works great expect I cannot retrieve the user's email address from acess-token.

 private string GetEmailFromIdToken(string token) {
        // JWT is made of three parts, separated by a '.' 
        // First part is the header 
        // Second part is the token 
        // Third part is the signature 
        string[] tokenParts = token.Split('.');
        if (tokenParts.Length < 3) {
            // Invalid token, return empty
        }
        // Token content is in the second part, in urlsafe base64
        string encodedToken = tokenParts[1];
        // Convert from urlsafe and add padding if needed
        int leftovers = encodedToken.Length % 4;
        if (leftovers == 2) {
            encodedToken += "==";
        } else if (leftovers == 3) {
            encodedToken += "=";
        }
        encodedToken = encodedToken.Replace('-', '+').Replace('_', '/');
        // Decode the string
        var base64EncodedBytes = System.Convert.FromBase64String(encodedToken);
        string decodedToken = System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
        // Load the decoded JSON into a dynamic object
        dynamic jwt = Newtonsoft.Json.JsonConvert.DeserializeObject(decodedToken);
        // User's email is in the preferred_username field
        return jwt.preferred_username;
    }

In some article people says to add "openid"

 private static string[] scopes = { "openid", "https://outlook.office.com/mail.read",
                                   "https://outlook.office.com/calendars.read" };

in the scope. However it still doesn't work. It doesn't even give a successful login, throws exception. When I don't add the "openid", I get a successful login however preferred_username is empty. enter image description here

Upvotes: 4

Views: 1801

Answers (2)

Jason Johnston
Jason Johnston

Reputation: 17692

I've seen some cases where the preferred_username claim isn't an SMTP address, so it's actually not the best way to get the user's email address. I'd recommend instead of parsing the ID token, just make an API call to GET /Me, which should include an EmailAddress property.

I'm reworking the tutorial on dev.outlook.com to do this.

Upvotes: 1

Jackie
Jackie

Reputation: 2030

That's a good catch!

You need to include the "profile" scope in order to read the preferred_username,

private static string[] scopes = { "profile",
                                       "https://outlook.office.com/mail.read",
                                       "https://outlook.office.com/calendars.read" };

Alternatively, try using the "contacts.read" scope

private static string[] scopes = { "https://outlook.office.com/contacts.read",
                                       "https://outlook.office.com/mail.read",
                                       "https://outlook.office.com/calendars.read" };

Find out more on the permission scopes in https://github.com/OfficeDev/microsoft-graph-docs/blob/master/content/authorization/permission_scopes.md

Upvotes: 2

Related Questions