Working with Azure for the first time. We want to be able to connect requests to our API to the user that made them. With the GraphServiceClient set up, it's easy to get the user information from Microsoft Graph on who made the request to the API:
graphServiceClient.Me.Request().GetAsync();
This gives us user information on the authenticated user making the request. We can pull out the ID and store that along with the request information.
The issue comes when we want to display who made the calls. At that point, it would be better to show the human readable Display Name instead of a GUID. So we'd like to call into Azure again with the ID and receive the display name. (And potentially the rest of the user information but for now at least, just the display name will do). In this case, we're not trying to get the information on the authenticated user making the request - we want our service to get display names for a collection of user IDs.
So in short: How do I call Azure to turn an ID into a display name? It seems like the Graph client should be able to do this, but we haven't been able to get it to work.
While we could create a table that stores all the information on the user and fill it when we first get the ID, that's not ideal. We'd just be duplicating information that it seems like we should be able to get from Azure again, and it could go out of date (eg someone changes their name and updates Azure, but our info wouldn't change until they made another request and we fetched it from Azure again)
EDIT
To try to simplify this/get rid of some of the context.
We have a list of some Azure user IDs. We want to use this to retrieve a list of corresponding DisplayNames from Azure. (Possibly we should be storing something other than ID and using that instead, but ID seems like the correct choice)
The call you have already has the display name. You can modify it slightly with Select depending on what fields are needed. For example, the request below gets the display name and job title.
var user = await graphClient.Me
.Request()
.Select(u => new {
u.DisplayName,
u.JobTitle
})
.GetAsync();
user.DisplayName is the property you need in this example.
Related
I´m currently working on a RESTful API, which has to give access to two diffrent Roles: Admin and User. (I'm wokring with Azure AD App Roles)
My Problem is that I don't understand how I can design the controller logic.
For example I want both (admin and user) to access the endpoint /books, but the admin is allowed to see all books and the user is only allowed to see his books.
What is the best practice to give both the allowed access? I thought of splitting it into two enpoints like this:
/books -> with annotation [Authorize(Roles="Admin")]
/user/{id}/books -> with annotation [Authorize(Roles="User")]
Thanks for helping!
Best regards
I think this sample may be of some help. And if you need sample written by other languages, you can refer to this document to find a suitable one.
And on your case, I think the most important thing is to find out the way to execute the right query and make the query result return to correct user.
So if you set a specific url for each user(I don't think this a good idea to expose user id in the request link), or you hide the user role/id into the token which contained in request header, you all need to write logic code to check which query method need to run. For example, hit domain:port/books with an access token, then your filter catch this request and decode the token to know the user id and user role, and maybe can save them in the session, then your controller may check the value stored in session and choose a right query to get the books information.
In my application I plan to use SignalR in order for the backend code to send messages to the logged in user based on the conditions that arise on the server.
In particular I want the SignalR to call methods on the JS client whenever something happens on the backend. This could be periodic calculations happening on the backend that suddenly pass a threshold and I need to invoke something on the JS client for a particular User. The particular User is the key element here. Only the User that should know about this.
I'm assuming this should be very simple with SignalR but I have some problem understanding the way to implement this. My solution is as follow;
Each time a user logs in, I create a SignalR Group and add that user to that group.
Each time a user logs out, I remove them from the Group. (I don't know if I can also delete the Group itself)
Now each time something happens on the back end, I use SignalR to push information to a particular User that needs to know about that event by calling a JS client method and sending to the group with the name equal to the Name Identifier of the user of interest.
So to apply this solution, I need to get the information about the User that just logged in inside the C# Hub in order to create the group and join him.
Now my problem is, how to access the information that I need from the User that logs in to the application in the C# Hub . I'm interested in the User Name Identifier of course. I have been thinking that the Context Property in the Hub should give me the information that I need (This is my understanding of the MS Docs) but I cannot make it to work. Please study below code.
// As soon as a User logs in, below method fires. I try to get the information
// in here but no success
public override async Task OnConnectedAsync()
{
var CID = Context.ConnectionId; // this gives a unique connection ID
var user = Context.User; // This returns nothing
var userID = Context.UserIdentifier; // This returns nothing
var httpContextObject = Context.GetHttpContext(); // This returns nothing
await base.OnConnectedAsync();
}
When I call other methods in the C# Hub from JS the method is fired and
information is passed but I still have no access to the information the
Context Property should provide.
Please help me first by confirming or correcting my overall approach and if there are well known best practices available. Secondly please let me know how can I get information that the Context Property provides in the Hub and generally where this information is available and how to access and use them.
Many thanks in advance.
'User' is a claims principle (normally stored in the asp cookie), to get the User form your Identity database use:
var user = await _userManager.GetUserAsync(User);
For future reference, your question is very long, you will get more help if you keep questions brief and to the point.
I've solved my problem by using Authentication with SignalR. I don't need to add a user to any groups to push massages to them. In the Startup class I add Authentication above SignalR service and then the user object is passed to the Hub in the Context property. I can also push to any user by injecting the IHubContext to any class constructor I need.
I am trying to use my Bot in Microsoft Teams and I have an issue when obtaining the username of each specific user that is using the Bot. A static variable cannot be used since there is only one server and multiple users. I am using this as a reference. Is there any way that I can make use of so that I can get each user's Username?
Please note that when a user interacts with your bot, you will receive the name in the From section of the payload. We will also be adding user name in the Roster retrieval functionality so you can retrieve all team member names along with their UIDs.
In general, if you want to store names for future messages (e.g. push messages vs response), you'd need to use something like Bot Framework's user data store or for more robust support, something like Azure's Table storage.
I just used the AuthResult class to get the user details. The following is the code that I write whenever I want to display the Username.
AuthResult authResult; context.UserData.TryGetValue(ContextConstants.AuthResultKey, out authResult);
And obtain the Username using authResult.
i.e. authResult.UserName
On my website, I display a list of media from a specific tag. When the user is authenticated I would like to visually mark the media that he has voted on.
Currently, the list I'm displaying is read from my own database. I have a synchronizing process that subscribes to the tag. When I get these values from the /tags/tag-name/media/recent end point, I am not authenticated as any user.
The way I had planned to do this is that when a user logs in to my website, I hit the /users/self/media/liked end point and store them in session (running c# / MVC4). But I'm looking at the JSON result from that endpoint and it's a complete "Medias response" type with paging and everything. Basically at 20 per page, if a user has liked some 250 media, logging in would require 24 API calls and would take too long.
How do you handle this issue?
I could save the them to database...
I could save the complete list of liking users as I synchronize my media...
Thanks!
When the user is authenticated and then if you make the recent tag API call /tags/tag-name/media/recent with the user's access_token, then the JSON response will have a "user_has_liked" element, this will be true if the user has liked the picture and false if not.
You can use this data to display if user have liked or not from a list of tag media. You dont have to get all user liked media and compare, instagram tag media API already has this information if you use the user's access_token to make tag media call.
What are some options in regards to maintaining user data while they are logged into my mvc4 site? I am building off of the Internet Application template and right now I am using User.Identity.Name to get the logged in user's username that they used to login with. I'd like to be able to also store and access several other pieces of information about the user across every page on the site. Can I still use User.Identity somehow and apply other attributes to it? I started building a ProfileModel that I could pass to views, but then I don't believe I would be able to pass other models to those views, not sure.
I'm open to suggestions as far as persistent user data, and thank you for any help.
EDIT 1: When I say persistent, I mean while they are logged in, the data itself is already stored in an external database, so I won't be doing any writing of this information, simply pulling it from the database, then holding onto it for the duration of them being logged in.
You'll want to leverage Session for that. Consider the following code:
Session["Profile"] = profileObj;
or maybe you just want to store a string:
Session["SomeSetting"] = value;
What you need to store in Session is unclear, and effectively irrelevant, you can store anything. You can access the Session from any Controller.
Then later on you can get the value out like this:
var profile = Session["Profile"];
// if the profile variable is null then it doesn't exist in Session yet
In response to #AaronLS, Session lasts the duration of the IIS session that's created when the user first accesses the site. Do keep in mind that these sessions are reset if inactive for a period of time (I believe the default IIS timeout is 20 minutes) so you'd want to leverage the null return value to know that you need to redirect the user to the login page to login again.