This post is not going to make any sense unless you understand OAuth2. Please read OAuth2 for dummies before reading this.
Office 365 APIs are protected by Azure AD, accessible via OAuth. Whether or not you can access any particular resource needs to know the desired scope and client ID.
But, to obtain an access token, you need the resource name/endpoint. Azure AD requires something called as the resourceURI.
The problem is – how to discover these resourceURIs – and that is where the discovery comes in.
Put simply, Discovery Service, is the service you can query using REST, the know about other services.
How does it work?
- User logs in, for a first time logon, the user is shown a common consent dialog for all services the app wishes to access. For Office 365 services, you receive access token(s) for each resource you wish to access, but you get a generic refresh token that can be used across all Office 365 services. At this point you get an access token for the discovery service, and a generic reusable refresh token that works across all of Office 365. Cool huh? I thought so too.
- You call the discovery service with the access token you got in step #1, and you are presented back a list of service endpoints the user is allowed to access.
- Now, with the refresh token you had in step #1 – you can get an access token for any of the services from step #2.
Show me some code
I know, I don’t understand theory unless I see code and understand the code. So, here is the “Easy Microsofty way”, download sample from github, add connected service, hit PLAY – wow it works! What did you learn? Damned near nothing. :-)
This is why I am not a fan of the current github documentation Microsoft is crazy about and sadly they are not listening to my feedback, maybe I am the only one who feels this way. But that aside .. lets learn!
To call discovery service, do this -
- Create a Visual Studio project – choose a Winforms app. Add connected service for Office 365, grant yourself some permissions. (this will register an app in Azure AD for you – I don’t like the blackboxy nature of this .. and there is a better way .. more on this below)
- Add nuget package for ADAL.
- Write code like this,
1: var discoveryClient = new DiscoveryClient(new Uri("https://api.office.com/discovery/v1.0/me/"),
4: string authority = "https://login.windows.net/winsmartsdev.onmicrosoft.com";
5: string clientID = "guidfromazuread";
6: Uri returnURI = new Uri("urifromazuread");
8: AuthenticationContext authContext = new AuthenticationContext(authority);
9: AuthenticationResult authResult =
10: authContext.AcquireToken("https://api.office.com/discovery/", clientID, returnURI);
11: return authResult.AccessToken;
13: var capabilities = await discoveryClient.DiscoverCapabilitiesAsync();
That’s it! The “capabilities” variable will contain a list of all services the user has access to, and their endpoints/resourceURIs etc.
Calling other Office 365 APIs is similarly easy.
Seems easy huh?
Well – until you see the “guidfromazuread” and “urifromazuread” – well WTF are those? The authority you can sort of guess .. but the GUID and URI .. no way you can guess those jose!
The thing is, when you do the right click/add connected service from Visual Studio – what it does is, it registers your native app in your Office 365 Azure AD. So for all the “dev work” you do, don’t forget to keep cleaning the Azure AD :). Yeah I don’t like it either :-) .. as a control freak developer, I want to know exactly what happens, I do not like blackboxes that leave cow dump droppings along the way for me to clean. ANYWAY .. there is a step by step manual way to do this, I’ll leave that for another day (its past 3AM here). BUT – from there, your already registered app, you can get the redirect URI and client ID from the registered app in Azure AD. There is also a way for your app to discover the redirect URI and client ID.
To get the client ID and return URI from Azure AD, do this -->
Step#1 – Login to Office 365 as admin, go to the right hand top gear, and choose Azure AD. If this is the first time you are doing this, you will be guided through a pretty simple wizard.
Step #2 – Once you are in your Azure AD portal, you should see your app already there. From that registered app, you can get the ClientID and RedirectURI.
Bingo! Now you know how it all works! Have fun!