What are the current OAuth URLs and scopes for Microsofts infrastructure? - azure

I am trying to build a bot that will need a basic outlook login. I was watching this video
https://channel9.msdn.com/events/Build/2017/P4063?term=cortana%20skill
and the guy at 17:02 adds the following values for scopes and Authorization and Token URLs:
wl.basic wl.birthday
https://login.live.com/oauth20_authorize.srf
https://login.live.com/oauth20_token.srf
then I stumbled across Microsoft's documentation:
https://learn.microsoft.com/en-us/cortana/tutorials/bot-skills/bot-skill-auth
where it says that the values for the scopes and URLs are:
User.Read offline_access openid
https://login.microsoftonline.com/common/oauth2/v2.0/authorize
https://login.microsoftonline.com/common/oauth2/v2.0/token
The video is from May 10, 2017 (which was the BUILD 2017), and the article is from April 08, 2017. So which one is correct/deprecated? Also I tried to mix them and this is what the Login prompt looks like with the different combinations:
As you can see all four variations of scopes/urls produce totally different sign in UI?!?!?! (and the ones at the right column also look slightly broken) Which is the correct way?
UPDATE
Also, following the article I added a singin card to my bot with the URL described in the documentation:
var message = context.MakeMessage() as IMessageActivity;
message.Speak = "This is a Sign-in card";
message.Summary = "This is a Sign-in card";
message.Text = "Message Text";
message.Attachments = new List<Attachment>(){
new SigninCard("You need to authorize me", new List<CardAction>()
{
new CardAction()
{
Value = "https://login.microsoftonline.com/?redirect_uri=http%3a%2f%2fbing.com%2fagents%2foauth",
Type = "signin",
Title = "Connect"
}
}).ToAttachment()
};
await context.PostAsync(message);
and to my surprise clicking the sign in button, an entirely new login UI, resembling Office 365 pops up:
UPDATE 2 FRESH!!!:
https://twitter.com/chriscapossela/status/888029356504645632

This answer requires a little bit of history :)
Back in the day, in order to authenticate Microsoft users, you had to know if the user had an OrgId (used to log into Microsoft's business services) or MSA (used to log into non-business Microsoft services) identity. For reasons I won't digress on, it resulted in two oAuth endpoints:
https://login.live.com/... is/was the token endpoint for MSA-specific identities
https://login.windows.net/[AAD-TENANT-ID]/... is/was the token endpoint for OrgID-specific identities
Understandably, developers got very upset about this. To solve this issue, Microsoft created the v2 app model, which allows you to use one AuthN/Z endpoint for both account types. The v2 app model does a lot of black magic to abstract away differences in consent, scopes, endpoints, etc between MSA and OrgID, so you as a developer don't have to worry about it.
However - some of our APIs, especially those created pre-v2 endpoint, are geared for a specific account type. The Live APIs, which Nafis uses in the Build demo, IIRC don't play well with OrgID identities - if the user logged into the v2 endpoint with their OrgId account, you'd get non-ideal behavior since the access token would be for an OrgID account. To prevent this skill-breaking behavior, he uses the MSA endpoint (live.com) directly, preventing OrgID users from logging in to the skill at all.
You're seeing the different UX when mixing URLs because the v1 and v2 endpoints provide different login UX. The error message in the last image seems to indicate that you're using a MSA identity to log into a converged API. $5 says that's related to the fact that you're mixing v1 and v2 endpoints/scopes/etc, but it's hard to tell without looking at the exact API call.
The CSK docs use the v2 endpoint because most of our APIs (including the mail/Outlook APIs, which are now part of the Microsoft Graph) use it these days. When I'm writing code utilizing MSFT services (or when I'm writing documentation for the services ;)), I default to the v2 app model unless the API docs specifically mention v1 endpoints, like the live API docs do.

Related

Programatically get users group and role from Azure AD

I am new to azure AD.
I have a third party API which gives me a userId. I have written a .NET Core API which should take this userID and get the roles and groups of that specific user.
I have read about the microsoft graph API. Not sure if this is useful in my scenario.
Also is there any other way to access the roles and groups of a AD user programatically.
Which API to use to get groups and role information
Firstly, Microsoft Graph API is your best bet to get the information you're looking for.
Which exact API works best for you depends on your scenario (a. do you need top level direct membership or transitive check? b. do you want only security groups or even O365 groups?), so you're the best judge.
I'll list down 3 of them here and you should get some ideas to pick.
memberOf -
Gets both groups and directory roles that user is a direct member of.
NOTE: only direct membership matters for this one, check is NOT transitive (i.e. User has to be a direct member of the group for that group to be returned. If user is member of a group1, but that group1 is member of group2, then group2 will NOT be returned. This behavior might be ok for some scenarios but not for others)
GET /users/{id | userPrincipalName}/memberOf
getMemberGroups
POST /users/{id | userPrincipalName}/getMemberGroups
Returns all the groups that the user is a member of. Check for this one is Transitive, so you're assured that all groups will be returned. Upto 2046 returned as part of 1 request. It also works with O365 groups and you can filter down to SecurityEnabled groups using a parameter
getMemberObjects
Returns all of the groups, directory roles and administrative units that the user is a member of. The check is again transitive.
Implementation and Code Sample.. How to get token, call API etc.
Acquiring Token for Authentication
You should make use of MSAL or ADAL libraries depending on which Azure AD endpoint you're using MSAL for v2 and ADAL for v1. Using these libraries is not mandatory but recommended because they will follow best practices and do the heavy lifting for you.
Interacting with Microsoft Graph API Endpoints
Since you're writing in .NET, you can make use of Microsoft Graph Client Library for .NET (SDK). Again, it's not mandatory to use the client library but it will make your code more declarative and will be convenient. You can always work with HttpClient and hit the REST endpoints directly if you want.
Code Sample
Microsoft Graph Connect Sample for ASP.NET Core 2.1
Important parts.. Look at the GraphService.cs file for methods that get user information, e.g.
// Load user's profile in formatted JSON.
public static async Task<string> GetUserJson(GraphServiceClient graphClient, string email, HttpContext httpContext)
{
if (email == null) return JsonConvert.SerializeObject(new { Message = "Email address cannot be null." }, Formatting.Indented);
try
{
// Load user profile.
var user = await graphClient.Users[email].Request().GetAsync();
return JsonConvert.SerializeObject(user, Formatting.Indented);
}
NOTE: The sample makes use of delegated permissions. You may need to make use of application permissions directly or On-behalf of flow (if you want to do it under a user's context) since you mention yours is an API being called. Also, this is just one of the samples, that you should look at to understand how to work with SDK, but there are many available readily once you start looking further into Microsoft Graph API and Client library documentation. I'll update the answer if I find a sample closer to your exact scenario.

401 Errors Calling the Microsoft Luis.ai Programmatic API

ASKING THIS HERE AT THE EXPLICIT REQUEST OF THE MICROSOFT AZURE SUPPORT TEAM.
I've been attempting to call the MS Luis.ai programmatic API (bit.ly/2iev01n) and have been receiving a 401 unauthorized response to every request. Here's a simple GET example: https://api.projectoxford.ai/luis/v1.0/prog/apps/{appId}/entities?subscription-key={subscription_key}.
I am providing my appId from the Luis.ai GUI (as specified by the API docs), here:
I am providing my subscription key from Azure (as specified by the API docs), here:
The app ID and subscription key, sourced from above, are the exact same as what I'm using to hit the query API successfully (see note at bottom). My account is pay-as-you-go (not free).
Am I doing something wrong here? Is this API deprecated, moved, down, or out-of-sync with the docs?
NOTE: I can manipulate my model through the online GUI but that approach will be far too manual for our business needs where our model will need to be programmatically updated as new business entities come into existence.
NOTE: The programmatic API is different from the query API which has this request URL, which is working fine for me:
https://api.projectoxford.ai/luis/v2.0/apps/{appId}?subscription-key={subscription_key}&verbose=true&q={utterance}
NOTE: There doesn't seem to be a Luis.ai programmatic API for v2.0--which is why the URLs from the query and programmatic APIs have different versions.
Answering my own question here:
I have found my LUIS.ai programmatic API key. It is found by:
LUIS.ai dashboard -> username (upper-right) -> settings in dropdown -> Subscription Keys tab -> Programmatic API Key
It was not immediately obvious since it's found nowhere else: not alongside any of the other key listings in cognitive services or the LUIS.
the programatic key for Luis is here ,
https://www.luis.ai/Home/UserSettings

Microsoft authentication ID

I have an app with a lot of users. I have now with an update decided I wanted to ask for their email. I am using Azure Mobile App Service, with microsoft authentication. Therefore I added the wl.basic and wl.emails.
I then read I could access the email by using:
var claimsPrincipal = User as ClaimsPrincipal;
string email = claimsPrincipal.FindFirst(ClaimTypes.Email).Value;
I however never got to try the above because I ran into another issue. I store the users data by the NameIdentifier from:
var claimsPrincipal = User as ClaimsPrincipal;
string sid = claimsPrincipal.FindFirst(ClaimTypes.NameIdentifier).Value;
The issue is that the sid is changing when I add more scopes to the login. My issue is therefore is there some way I can extract an identifier that goes across this ?
This is a known issue. See this wiki post for more information about how to get stable identifiers for your users.
https://github.com/Azure/azure-mobile-apps-net-server/wiki/Understanding-User-Ids
Here is a snippet from the page which introduces the problem:
When App Service Authentication was first released, the sid was generated based on the email of the user. This made it great for linking a user across two providers if they used the same email for google, facebook and twitter, but it meant that the sid was not stable. Someone could change their registered Facebook email and suddenly the sid would be different. This is why this wiki page was written -- to show how you could generate your own stable user ids.
The page goes on to explain how to get the stable identifiers and the options you have for doing this kind of migration.

Error from Instagram: The access_token provided does not match an approved application

This was working fine for many months and now it's just a blank space. I get the following error: Error from Instagram: The access_token provided does not match an approved application. How can I get a new access_token for an existing client??
You need to check you application hasn't been put into sandbox by Instagram. They made big changes to their API on the 1st of June and if you had it submitted your app for review it will be put in sandbox mode and only sandbox users will be able to use it.
Even if you are not in sandbox mode you may need to get your users to reaurhorize your app due to new scopes being used to control access to everything other than basic user information.
Check Instagram Developer Docs for more information on the changes
You need to check your Access token's Scope and asking for login permission
where some new Scope had been added ex:public_content Added. Also don't forget to check for requirements Scope for API you are using and if it's need and Authentications "Valid access Token". where also had some changes.
basic - to read a user’s profile info and media
public_content to read any public profile info and media on a user’s behalf
follower_list to read the list of followers and followed-by users
comments - to post and delete comments on a user’s behalf
relationships - to follow and unfollow accounts on a user’s behalf
likes - to like and unlike media on a user’s behalf
And take look about **Sandbox API behavior of your application not life yet :**
API Behavior
The behavior of the API when you are in sandbox mode is the same as when your app is live, but comes with the following restrictions:
Data is restricted to sandbox users and the 20 most recent media from each sandbox user
Reduced API rate limits
The first point is important and it means that the API behaves as if the only users on Instagram were your sandbox users, and the only media ever posted were the last 20 for each of these users.
For example, if you query the /users/{user-id}/ endpoint and the {user-id} is a sandbox user, then you will get the normal API response; but if the {user-id} is not a sandbox user, you will get a APINotFound error.
As another example, let's consider an endpoint that returns a list of media: /tags/{tag-name}/media/recent. The response returned by this endpoint will contain only media with the given tag, as expected. But instead of returning media from any public Instagram user, it will return only media that belongs to your sandbox users, restricted to the last 20 for each user.
Good luck
The following video clearly explains what steps to follow to get this working with the new auth
https://www.youtube.com/watch?v=0k4RhTS94Hw
Kind Regards
Sandeep Sahoo

How do I access data for all of my students?

I'm making an app that authenticates a coach with KA's API, in order to present statistics and reports on the progress of each student.
How do I see "For whom am I a coach" (inverse of /api/v1/user.coaches)?
or otherwise request user and progress data for all my students?
You can request /api/v1/user/students to get a list of the currently authenticated users' students. Note that this is an undocumented endpoint, not sure if that's on purpose or not, but I suspect just an oversight because IIRC I've seen them reference it on github issues in the past.
I added that endpoint to the khan npm module in this PR: https://github.com/weo-edu/khan/pull/4
An important caveat to note is that as of this writing, you won't be able to request students on behalf of a user who has authenticated your application, only the user who created the app you're currently using.
Put another way: If I create an application called "hello" while logged in as "Jeffrey", I can get all of Jeffrey's students by authenticating with the "hello" app. However, If I log in as Lisa via the "hello" app (via oauth, e.g. passport-khan), I'll have an access token but the Khan API will refuse my request because Lisa did not create the "hello" app.
This behavior is documented (albeit a bit confusingly) in this wiki page, here's the relevant paragraph:
It is recommended that schools have one teacher/coach account that registers for an API key. This enables a situation where the logged-in user is the same as the third-party developer, who then can access their own students' data pursuant to Khan Academy's "coach" relationship. For example, suppose the principal of Riverdale High wished to export data for multiple students via the API. The principal would create a teacher/coach account, perhaps called "RiverdaleHighAPI," and register for an API key. The principal would then ask all students of Riverdale High to add "RiverdaleHighAPI" as a coach, either directly or via several class codes. When accessing the API with "RiverdaleHighAPI" as the logged in user, the principal would be able to access the data for all students that have added "RiverdaleHighAPI" as a coach. The app would not have access to any other coaches' student data, even if another coach logged in through the app. To protect student privacy, we do not allow indirect consent through the coach, and we require each student to explicitly grant permission to access their data. Please note that we are working to improve this functionality; for the time being, this "RiverdaleHighAPI" account should only be used by the school's API client, not by any actual teacher or coach.
Lastly, khan actually encourages public use of their internal API. They recommend opening up your developer console while logged in to khan and looking for the endpoints that return the data you want. (see this note on their authentication document).
This is obviously a fairly non-standard practice and I assume the endpoints would be subject to breaking changes without warning. Also you'll be flying documentation free. That said, this approach may be the most robust option for your purposes. Here's the quote from their wiki for posterity:
The API explorer documents our public API, which has URLs starting with /api/v1, but unfortunately it's not very well-maintained and lacking in a few areas.
If you're feeling adventurous, though, you're welcome to use any internal undocumented API endpoints. For example, if you load a Khan Academy video page and use your browser's developer tools to look at the ajax requests being sent, you'll see that it gets a URL like /api/internal/videos/aubZU0iWtgI/transcript, which contains a JSON response with the video subtitles. That "internal" in the name means that we don't provide documentation, and we may remove the endpoint or change the format in the future, but you're welcome to use any internal endpoints if you keep those caveats in mind.

Resources