Changing the membership providers ApplicationName during runtime. How? - c#

I have a bit of a unique situation here. I'm making a web application that is going to have
the ability to login with different web applications credentials. For example you can login/register with my site or you can login/register with your YouTube account. I'm not using OpenID because I need to have access to YouTube's data in this case.
I'm using ASP.NET MVC 3 EF4 with custom Membership, role, profile providers.
The problem is user names can't be unique because someone with a YouTube user name could have the same user name as someone that registered with my site. So I got around with by specifying a user type in my user table. This is pretty much a composite key (user id and user type).
I have a custom authorize attribute that is checking for the role that the user is in but now I need to implement a custom IPrincipal because I need to pass a user type. Only problem is where do I store that? the session?
Originally I thought this is what the Application table was for, and I had momentary success with that but read there is threading issues, and I was getting session faults all over the place it wasn't that great :(
I'm wondering what the best way to do with is because I can't use the overridden methods in the providers because I have to add a UserType parameter to some of the methods, but then this breaks the functionality of the provider.
EDIT:
I basically need to have the ability to change the ApplicationName at runtime pro-grammatically. I tried doing this, the only problem was when I stopped my development server but left my browser open then ran my dev server again it wouldnt keep the application name.
EDIT:
I've changed my application to use OAuth, I never found a good solution.

I basically need to have the ability
to change the ApplicationName at
runtime pro-grammatically. I tried
doing this, the only problem was when
I stopped my development server but
left my browser open then ran my dev
server again it wouldnt keep the
application name.
If you need to change the ApplicationName, this means you need to select a provider at runtime.
The only way to do this is to NOT use the singleton "Membership" as it uses the provider defined in web.config.
Instead each time you need your provider use :
MembershipProvider userProvider = Membership.Providers[UserProviderName];
Just set UserProviderName the way you want. I would go with a custom global authorization or preAction filter which detect the provider from some cookie or other session variable and put the provider in the HttpContextBase.Items collection which lives for one and only one request.

The best answer to this problem is answered on stackoverflow here: Membership provider with different ApplicationName in area
Here's the code they used:
Membership.Providers["MyOtherProvider"].ValidateUser(username, pwd);

Ryan,
Hmmm... can you work-around the problem by prepending the issuing-authority (local or YouTube) to the username field itself... Example usernames: "LOCAL/corlettk", "YOUTUBE/corlettk"???
Ok, you'll need a custom Authenticator in order to split the complex-string, and flick-pass the login-request to appropriate underlying Authenticator... but once that's done, (I guess) you're all set to deal EASILY with the much bigger problem (from your perspective) of Authorisation.
I percieve that you're a smart guy... have you considered-and-dismissed this approach allready?
Cheers. Keith.
PS: Yes, I'm a hacker... but I have bad habit of hacking stuff up that WORKS... so they've given-up trying to educate me.

Related

Record Login Date/time

We are using IdentityServer 4 as our login server, in conjunction with Web API 2.0 and Angular 5.
I have been asked to record the date and time that users log in, which doesn't seem too unreasonable. IdentityServer 4 doesn't do this by default.
I thought the most sensible thing to do would be to add a LoginTime column to the AspNetUsers table and a corresponding property to the ApplicationUser class, then I could just set this during the login process. I can't change the actual login code as this takes place in the UserManager class but I thought I could add my own additional code, for example in the controller method, or an abstraction of it anyway.
But, I can't seem to trap the login endpoint call. I have breakpoints everywhere and none of them are being hit, and anyway none seem to have a signature matching the data being posted. The dev tools in Chrome tell me that the call looks like it's going to 'roughly' the right place, but I'm beginning to think that the endpoint itself is embedded in the API somewhere I don't have access to.
I guess it's possible that this is a config option, but if so I can't find out which one.
This being the case, how can I extend the login method to record the date and time? I have searched online to find how to extend the login process but can't find it anywhere.
This needs to be done at the same time as the authentication token is created. A second call from the client could in theory be bypassed and this would not be good.
I was going to post some code here as I know it'll probably be asked for, but it doesn't seem relevant as I can't find the right endpoint anyway!
How can I extend the login endpoint to save the date and time users log in?

Is there a way to customize the Thinktecture.IdentityServer.v2 login page?

I'm using the Thinktecture.IdentityServer.v2 app to perform SSO for a couple of internal apps but would like to customize the login page for each application to have a smoother user experience. I can't seem to find a way to do that.
Can the login page be customized depending on the source application from where the client is comming?
"I can't seem to find a way to do that." - How hard have you tried? ;)
The RP has the extra data fields - so you can hang like a CSS name off the RP in the registration database. Further you can get to that RP data from the signin page - quoting the comment in AccountController:
// you can call AuthenticationHelper.GetRelyingPartyDetailsFromReturnUrl to get more information about the requested relying party
btw - IdentityServer's github repo has an issue tracker - you should use that for questions.
You can always have the RP pass a custom query string param and customize off of that. But you're outside the bounds of WS-Federation at that point. Plus, you must think about the nature of SSO -- the user is really signing into the IdP, not the app. So changing the IdP to look like the app is somewhat disingenuous.
I have solved this by customizing the SignIn.cshtml to adjust the style to what I need. Additionally, I have server side code in the top of SignIn.cshtml that does some string matching on the ReturnUrl (Request.QueryString["ReturnUrl"]). Then I show a different logo and header text based on some values I know to be unique for the different RP urls.
When upgrading to a new version of the ThinkTecture MVC, it will be a small job to update only this file to your specifics (just remember to have a copy of your modified SignIn.cshtml before you upgrade).

Set active membership provider programmatically

I have a web application with custom membership providers. The provider I want to use connects to a Progress database.
I have one page that uses a competely different membership provider. I've tried setting this via the web.config but cannot get it working.
So I was wondering if I could set the membership provider programmatically for this page. I see here that it is possible on some level though this looks pretty hacky. I was hoping there'd be a clean way of doing this one way or another. Everything else on SO or the wider web seems to end in a dead end. This suggests to me that what I'm attempting is not possible but it would be nice to know either way.
Is it possible to simply switch the MembershipProvider at runtime?
This is not an ideal solution but you can select a different provider at runtime.
var p = (ProgressMembershipProvider)Membership.Providers["ProgressProvider"];
var user = p.GetUser("Foo", true);

Adding Windows User Name to database

ASP.NET MVC3 newb here.
I am working on a MVC3 intranet application that uses windows authentication. Windows auth is setup and ready to go no problem.
What I need to happen is to capture the username (Domain\first.last) whenever a user accesses the app for the first time and then store that information into a database and associate that name to a another unique identifier (numeric and auto-incremented).
I already found a way to get the username:
string user = WindowsIdentity.GetCurrent().Name;
What I am having an issue with is taking that variable and storing it in my database.
Any suggestions, hints, tips or nudges towards helpful resources are greatly appreciated.
Apologies if this scenario was posted elsewhere, if it was then I was unable to locate it.
Cheers Guys!
Be careful - user names and display names can change. I would avoid storing them in the database.
Instead, look at storing the SID (id of the user). The User property of the WindowsIdentity returns the SID. You can store and update the user name for display purposes but don't rely on it for typing the authenticating user back to the previous user in your DB.
See this SO post as well:
How can I get the SID of the current Windows account?
Persist the SID (along with username for display only) and look up via SID.
I think what you are looking for here is really 'how to store some info in a database'
What database system?
Check out
http://www.datasprings.com/resources/articles-information/a-quick-guide-to-using-entity-framework
You can easily use the entity framework to store that value in the database which is what I think your question was really about. I do agree with Bryanmac though, you should be storing the SID not the login name in case the name changes. If you know it will NEVER change then you could store the name, but since they can technically change in Windows, I'd be aware of this.
If you have a specific question then on how to store that field using the Entity Framework, please post that.
When you create your MVC3 application, there is an option for "Intranet Application" that has all of the Windows Authentication stuff working already, you might want to check that out and pull over pieces of the code for your current project (or migrate what you have depending on how far you are).
It has some special code placed into Web.Config as well as the extra files it creates.
Read more here:
http://weblogs.asp.net/gunnarpeipman/archive/2011/04/14/asp-net-mvc-3-intranet-application-template.aspx
and here:
http://msdn.microsoft.com/en-us/library/gg703322%28VS.98%29.aspx
Also you'll want to use User.Identity.Name to reference the person viewing the website.

What can I use in Place of URL Referrer check to know where the request is coming from on my domain?

I have to implement a single signon kind of solution on my website. Let's say my website is www.myweb.com and I want to allow the users to use this site who only come from a site www.sourceweb.com.
I thought URL Referrer would do but in IE may comes null.
See here
Please suggest me some alternate solution.
Thanks,
Gaurav
If you have access to www.sourceweb.com and can modify the source then a possible solution would be:
Create a webservice on www.myweb.com.
Create a link on www.sourceweb.com
When the link is clicked call the webservice to retrieve a unique id.
Redirect the user to www.myweb.com and provide the unique id in the querystring.
On www.myweb.com confirm that the unique id is valid and remove it/mark it as used.
There are many ways to skin a cat, one way in your case would be to set a cookie on the 2nd site, using a pixel gif (1x1 pixel small picture) embedded on a page of the main site. The 2nd site then can later allow access only when the cookie is already set.
To make this secure, you have to add a token to the pixel gif URL, containing a timestamp and signed using a HMAC or something similar establishing a shared secret with the other site. Then you only set the cookie when the timestamp is recent (less than a minute ago) and properly signed.
URL_REFERER is your best bet.
Keep in mind that like most HTTP headers, it is easy to forge and does not have to be provided.
The very short answer. Don't implement this yourself.
Security solutions should not be implemented but bought. The only exception being if you actually develops security solutions for other to buy of course.
Choose one of many available SSO solutions and go with that. We use Microsofts ADFS, though not perfect it gets the job done for us with very little maintance and the only real hazle is for our applications hosted on non-windows platforms like AIX.
There so many chance of screwing things up when you try to implement your own security solutions. If you disagree than just remember than anual contests are held to break the security systems of companies such as Apple,Microsoft,Mozilla and Goggle and most of the years some one takes home the price for breaking each of them.

Categories

Resources