I am working on a C# WebApi/MVC project that has a rather large workflow process for creating a user and placing in their required information.
There is about 10 major steps involved, in which it could technically take a user hours to fill out.
The first step takes standard basic information such as username, password, email, name, address etc.
What I would like to do is after this first step is successful, send a rest call that will create the basic user in the user table, and then prepare a session for the further steps in which when any field is filled out in the next steps, it will automatically send an ajax call and update the field in the database.
While this all sounds easy and simple in theory with the use of sessions, which I could do in MVC, I want to do this in WebApi with REST in which REST is supposed to be STATELESS.
Has anyone come across similar issues, and if so what do they recommend as an approach? The options I can currently think of are:
-Ditch the REST for standard MVC for this process and leave WebAPI for only Reads instead of Writes as the only Write process is the inital creation of users/accounts.
-Using Authentication tokens? But can this handle this process successfully?
-Once the user is created, take the username/password for every REST call as the auth to the WebAPI? Store the User/Password in MVC session and directly call the API from MVC, mobile applications would just store the username/password in the application and call the WebAPI (I think this is the most appropriate)
Can anyone tell me if any of those options are the best practice, or does anyone have a better best practice/process for these things? I would prefer to write things once to cover Web and Mobile as much as possible rather than having to duplicate processes.
Thanks in advance!!!
I would consider to modify regular WebAPI OWIN register flow.
Collect basic user info and post to Web API via Ajax. If succeeded -
send OWIN token back to the caller in HTTP header.
Proceed to extra
steps for user info updates (via HTTP PUT for example) and put the
token in authenticate header. Mark WebAPI update procedure with
Authorize attribute.
This blog post could help to setup WebAPI to issue and accept bearer tokens.
Related
Ok so I think I've settled on choosing BLAZOR for my upcoming project. But first I need to do something that is seemingly very basic.
For context, Blazor Server side will be how I interface with my SQL Server dB, I want "individual accounts" mode to be the way users authenticate. I'm using net 6.0,almost all tutorials out there seem to be net 5 since they all still have startup.cs files. Ok, but I also am creating a parallel app that is NOT a website, but I want it to grab data from the same database via routes after authenticating.
For example, website.com/api/data?variablestograb as a GET would send me some json data.
OK that being said, how do I login programmatically from an outside app? If you must know, the outside app is part of Unity C#. But that doesn't matter so much, what itll do is use a post call to login in via the api routes. Something like
Website.com/api/login?un=blah&pw=haha
This will generate a cookie and I can grab it with the session data and I'll use this with every get call hence.
Just using the basic templates, Blazor server net 6.0 with individual auth, how do I set up such a route? Looking at the files, I'm at a complete loss on how the login pages are actually passing data around.
Thanks!
Update: the specific ask is exactly how do I modify the Blazor Server Net 6 Individual Accounts template to allow me to authenticate a user via an external access api? My thought would be to reference the route above for /login/ but that might not even be the best practice. But even if it is, how exactly and where would I update the template to make this happen?
(I have a feeling it's pretty basic to do, but I've been reading tutorials for weeks now and they're all just talking about internal authentication and verification within each Blazor component. I basically want an external program to also be able to "drive the car" remotely, but first it must authenticate.)
If you're building an API for this from scratch, then it seems like you have the right idea, no matter what happens, you're going to send the cookie to be website every request or at least a session id which contains all the information provided. From a database perspective maybe create a session table which then contains all the info you want and also can be easily found. That's a way for you to create a cookie for client server communication, however this is from my limited knowledge and may not be the best way.
I'd recommend hiding information like keys in the header to prevent exposure, looking at other APIs like the Spotify API you can see they set the authorisation bearer.
Exposing all the information for the credentials in the URL for what could be sensitive database behaviour may not be the best. You can hide the information in the header for every request you make.
Maybe have a default controller that obtains the user information before handling any specific requests and making it accessible to your other methods/requests?
The basic process for any external authentication is:
Redirect to the external log in page.
External Provider does it business.
External provider posts to a page on your site with the authentication information included - normally security info in the header or a cookie.
The Blazor app reads the authentication information with the AuthenticationStateProvider.
Normally you just need to write a customer AuthenticationStateProvider and code to redirect if the user is not authorized. This may be a manual button in the top bar, a you aren't logged in page with a button to log in, or an automatic redirect to the provider. The return for the provider is either your landing page or some other page to tell them they logged in successfully.
The custom AuthenticationStateProvider replaces the standard one in DI services and provides the security information to the Authorization components.
Search for "blazor custom authentication provider" will get you lots of good resources.
I have a web app (rest API) on azure, and I have a B2C setup that is securing it, requiring you to be signed in to access the API. This is good, as i wanted the API to be restricted to members. Basically, the entire web app requires authentication, and will prompt you for a sign in.
Heres the problem - my app has users (who have accounts) and clients (who do not have accounts). These clients might receive an email about a new appointment being set up with one of the users - this email should have one or more links/buttons (ie, a button to Confirm appointment, one to Decline, and one to request a reschdeule) and upon clicking this link I would like to update a field in my database via the rest api, so the USER knows the CLIENT's response. The trouble is, since the client wont have an account, I have no idea how I can give them a link they would be allowed to go to, and have the update happen.
I have tried to do a bunch of research - ive looked into AD external identities with a one time passcode - but i cant seem to find any info on how i would actually get this to work for my purposes.
Does anyone know how I might implement this in azure? Is there a way to call to azure form c# to generate a one time authentication that i can encode into a URL or something?
Any thoughts would be greatly appreciated.
Thanks!
You could do an anonymous authentication by using a magic link. The users account won’t even need to live in the directory. The link can be short lived, and potentially one time use. We call it id_token_hint or a magic link.
Sample here
https://github.com/azure-ad-b2c/samples/tree/master/policies/invite
And reference here
https://learn.microsoft.com/en-us/azure/active-directory-b2c/id-token-hint
We've made an asp.net mvc application which has an affiliates program.
Our affiliates want the possibility to let their customers, probably using a background code (not a form) logging in to our application.
After making the login the user is supposed to be redirected to one of our own URLs.
First of all, we need some help and example of how to do this.
Second of all in case it's indeed possible, allowing this is in fact a cross site scripting right? so does it expose us to attacks?
Any help would be appreciated.
A simple link couldn't do this safely, the only way to redirect is with a GET, and you never want to pass re-usable login information that way
Here is an option for you... provide an external facing controller that functions like a web service. Include at least the following two actions. One to request a new account from your site, passing in whatever information is necessary, and another to serve as a 'remote login.' Both of these Actions should only accept POSTs and require HTTPS. Inside, they should not accept any transfers of data via Query String, look in the POST object (this is encrypted, and thus, safer).
The 'remote login' action should take their username and password as passed by your affiliate (encrypted in the POST object) and verify that it is valid. It should then generate a new random value, a good thing to use is a GUID, and return it. The affiliate then redirects them to your site, passing the GUID in the query string. The GUID serves as their single-use login token (they will need a new GUID to log in next time).
If they don't need a specific account to do stuff on your site, then you could leave out the 'create account' and simply give your affiliate a code that they send the remote login function to confirm that it is them asking for a login.
What your affiliate would have to do (and you could give them this chunk of code in a single piece and say 'put this on your page, and it will work.') for the actual remote login is to make an AJAX call to your site, requesting the GUID for a one-time login. When it receives said GUID, it will then redirect to your site.
This isn't the best option possible...single-sign-on like behaviors are best when both sides work together to keep things secure and invisible to users, but it is workable and reasonably secure.
I have a web application that has implemented the latest Web API as a restful server for a mostly javascript/ajax based web application built on .NET 4.5. I'm using forms authentication and its working as it should to secure the web api as well as the rest of the application.
I'm wanting to add another layer of security to the Web API to prevent users from using another user guid in a manual request to the API. They would have to view the source in another logged in user's browser to get that user's guid from a hidden input. They could then potentially use that guid to access the other user's data through their own authenticated session. Of course this bad person would have to be authenticated under their own account for this to work.
What I'm thinking of doing is passing the user guid with every api request and if that guid matches HttpContext.Current.User.Identity.Name then allow the request...otherwise throw an unauthorized exception and handle it on the client accordingly. But then all of my handler methods become a bit dirty as shown below...this would have to be in each and every GET, POST, PUT, etc... along with other objects in most cases.
public Community Get(string userGuid)
{
if (HttpContext.Current.User.Identity.Name == userGuid)
return myDataHandler.getUserData();
else
throw new HttpResponseException(HttpStatusCode.Unauthorized);
}
I can make this work but it seems like a bit too much overhead. I've looked at numerous posts and articles regarding web api security but nothing regarding this potential situation. What is the best way to verify every request is actually requesting information regarding the user logged in without having to do what I'm doing above? Possibly use this idea but do it globally for each api request instead of it being tested in every method? Another way around this is to user HttpContext.Current.User.Identity.Name for every request instead of relying on what is sent from the client...but I'm not sure this will work in all of my situations...as my application is still young.
Thank you for your time!
I'm currently putting together an API which uses bearer authentication (See Microsoft documentation here as there is too much detail to post here).
One thing I am using are Claims, and one of the claims I am setting is a User ID which forms part of a User Identity. When someone authenticates with the API the claims are also set (read from the token) and can be accessed from the User Context as you are currently doing to access the name.
By doing it that way you don't need to store the Guid in a hidden field.
So according to the documentation for the SOAP api for Salesforce, if I log in and start a process that takes 1 minute before I log out, then someone else logs in with the same credentials and begins another process that takes 30 seconds before logout, when the second user logs out, it will kick out the first user as well.
Does the REST api have this issue? Is there a way around it?
The answer of your question is YES, REST Api has the same issue.
From official documentation:
If multiple client applications are logged in using the same user,
they all share the same session. If one of the client applications
calls logout(), it invalidates the session for all the client
applications. Using a different user for each client application makes
it easier to avoid these limits.
The only way that salesforce recommends us to avoid this is creating new users.
You could make your own central service to manage the unique session, and give the active access token to clients, but this approach is away force.com platform solutions.
This is really a session management issue more than any specific API you want to call using that session. that said, you have 2 easy options.
a) don't call logout, just let the sessions expire based on inactivity, that way if the session happens to be shared by 2 different integrations it won't cause a problem.
b) switch to OAuth to do your authentication, and give each integration its own OAuth client/remote access entry. (sessions are not shared between different oauth clients).