Using user's liked media in a list - c#

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.

Related

How do I get a Display Name from an Azure ID?

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.

How to Logout user from a particular session Identity Server 4, .Net Core?

Using Identity Serve 4 with .Net Core 3.1, razor pages. Also using Cookie Authentication
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
Problem -
In a web application John logged-in 2 times
1st Login on Chrome
2nd Login on edge
So, if John again trying to logged-in on 3rd time on Firefox without logout from previous browsers, then I want to logout John from 1st Login on Chrome forcefully.
I can keep the track of logins in a Session table including Session Id, User Id etc.
But I don’t know how logout user from a particular session using Session Id.
Please help.
Thanks
ASP.NET Core provides an ITicketStore interface which allows you to get control of storing user sessions. Once you provide a class implementing this interface and register it, it will call your class when sessions are being created or verified which you can then store in a database however you like, including attaching arbitrary metadata like browser ID etc.
Now that you have user sessions in your database, you can separately query them and revoke as needed in other logic, including during logins. Since you now provide the session data, simply deleting the record effectively logs the user out from that session. Note that if you use any caching layer to reduce the store requests, you'd need to remove any cached copies as well.
Note that this is separate from IdentityServer and happens with ASP.NET Core itself.
This is a good tutorial that helped me implementing this in my app.
A sample of how it looks to register in Startup, where PersistentTicketStore is my implementation:
// Persistent ticket/cookie store to provide durable user sessions
services.AddSingleton<IUserSessionRepository, UserSessionRepository>();
services.AddSingleton<ITicketStore, PersistentTicketStore>();
services.AddOptions<CookieAuthenticationOptions>(CookieAuthenticationDefaults.AuthenticationScheme)
.Configure<ITicketStore>((options, store) => options.SessionStore = store);
Use the End Session Endpoint
The end session endpoint can be used to end a session and trigger a log out
In the log in process you will need to capture the id_token received from authentication and what user it belongs and store it on some dbo.table. You can use this same table to also keep track if a user has logged in more than once.
To log out a user or end a session you will need to pass the ID you saved as a query string parameter called id_token_hint in a GET call as shown below into:
GET /connect/endsession?id_token_hint={id_token}
For reference see the documentation here https://identityserver4.readthedocs.io/en/latest/endpoints/endsession.html#end-session-endpoint
Since you're saying you can keep track of logins, perhaps you should keep track of each session and assign a number somewhere indicating when it was logged in (1 for Chrome, 2 for edge, 3 for Firefox).
Then each time a request is made, you check in your table what the lowest number is (1,2,3 etc), and if the session matches that number, you sign the user out from that session.
await
HttpContext.SignOutAsync(IdentityServerConstants.DefaultCookieAuthenticationScheme);
Since each browser will have their own cookie, you can use the above method.
After signing someone out, the next login can be assigned 4, and if 2 makes a request you log that client out.....
Also see this: https://github.com/IdentityServer/IdentityServer4/issues/736
I have implemented this.
When a user logs in, the session id (IUserSession.GetSessionIdAsync) is manually stored in our database. The previous value of this database field is used to create a logout_token which I send to my clients. You can have look at IdentityServer4.Infrastructure.BackChannelLogoutClient to figure out how to create the token and post.
All this assumes you have backchannel logout implemented ofcourse.

Redirect from successful stripe checkout

I am using Stripes payment gateway with C# .Net. I started with creating a checkout which redirects the user to Stripe's payment gateway (I didnt want the hassle of maintaining the card numbers etc so this way it forwards to Stripe to ask for the card details, process the payment etc) https://stripe.com/docs/payments/checkout/one-time - this was done in code-behind.
I set my success URL as www.example.com/myHandler.ashx (Generic Handler)- this URL sets the order id as successful. My handler code is similar to https://stripe.com/docs/webhooks/build (since im using a Generic Handler i'm using forms and not MVC)
After a successful payment, the payment is recorded to my database.
Considering this is a webhook, how do i display/redirect to a thank you page?
You have more than one way to solve this.
Option 1:
Combine the success page with your webhook. This means it will display the page to the user and update the state of the transaction on the backend.
your url would look like this
SuccessUrl = "https://example.com/success?session_id={CHECKOUT_SESSION_ID}"
Then use the session ID to handle the state change like you would with your webhook but return the html page to the user (Technically this wouldn't be a webhook).
Based on your question it could be that the SuccessUrl gives a session object as body because otherwise your current code shouldn't be working but I'm not sure.
To get the session object based on the Id you can make another call to stripe see:
https://stripe.com/docs/api/checkout/sessions/retrieve#retrieve_checkout_session
Once payment is successful, the Checkout Session will contain a reference to the Customer, and either the successful PaymentIntent or an active Subscription.
Option 2:
Create a webhook separately from your thank you page. This means that the SuccessUrl would be your thank you page.
The webhook needs to be defined separately and globally with stripe. You can look here on how this is done: https://stripe.com/docs/webhooks/configure

remember anonymous users when navigating

I'm trying to make a game with SignalR that can be played between two players.
I have an issue in remembering the anonymus players. At one point, the users are redirected to another page and there I'm lost.
Inspired by Mapping connections , I've been able to solve the authenticated users ( Context.User.Identity.Name ), but what should I do in order to remember the unaunthenticated users when they navigate through website? (from what I know the signalR ConnectionId changes every request).
Generate a cookie for them containing a random GUID and then use that in your connection mapping. Set the value as part of the initial HTML you send the browser. Read the value in your Hub via Context.RequestCookies.

Options for storing user information while logged in

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.

Categories