When ApplicationID is generated in Membership.CreateUser method? - asp.net

I was working with ASP.Net Membership and was wondering when exactly ApplicationID is generated. I want to know what events are called and when does ApplicationID is generated when we use "Membership.CreateUser" method.
I googled it for some time but couldn't find any satisfactory answer.
Can anyone explain what is the working of this method?
Thanks

I want to know what events are called and when does ApplicationID is
generated when we use "Membership.CreateUser" method.
Right before processing any request to Membership table (such as select/insert/update/delete), Application is retrieved by applicationName.
For example, inside the Membership.CreateUser method, QueryHelper.GetApplication is called right before creating a new user.
Application application = QueryHelper.GetApplication(membershipEntity,
applicationName);
// QueryHelper.GetApplication
internal static Application GetApplication(MembershipEntities ctx,
string applicationName)
{
ObjectParameter[] objectParameter = new ObjectParameter[1];
objectParameter[0] = new ObjectParameter("name",
applicationName.ToLowerInvariant());
Application application = ctx.CreateQuery<Application>(
"select value a FROM Applications as a WHERE ToLower(a.ApplicationName) = #name",
objectParameter).FirstOrDefault<Application>();
return application;
}
If application is null, it is created an application like this -
internal static Application CreateApplication(MembershipEntities ctx,
string appName)
{
Application application = new Application();
application.ApplicationId = Guid.NewGuid();
application.ApplicationName = appName;
ctx.Applications.AddObject(application);
Application application1 = application;
return application1;
}
About code is from ASP.NET Universal Providers. Legacy Membership Provider uses Store Procedure, but the logic is almost same.

Related

How to get JdbcClientTokenServices to store tokens in datasource?

Here is my code, I need to setMandatory to 'false' because the resource provider does not return the 'state' parameter as the Oauth2 specification recommends.
#Bean
#Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
public OAuth2RestOperations restTemplate() {
OAuth2RestTemplate template = new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(accessTokenRequest));
AuthorizationCodeAccessTokenProvider authorizationCodeAccessTokenProvider = new AuthorizationCodeAccessTokenProvider();
authorizationCodeAccessTokenProvider.setStateMandatory(false);
AccessTokenProviderChain provider = new AccessTokenProviderChain(Arrays.asList(authorizationCodeAccessTokenProvider));
provider.setClientTokenServices(clientTokenServices());
template.setAccessTokenProvider(provider);
return template;
}
Here is the code from the github example that works with H2:
#Bean
#Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
public OAuth2RestOperations restTemplate() {
OAuth2RestTemplate template = new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(accessTokenRequest));
AccessTokenProviderChain provider = new AccessTokenProviderChain(Arrays.asList(new AuthorizationCodeAccessTokenProvider()));
provider.setClientTokenServices(clientTokenServices());
return template;
}
I changed the LONGVARBINARY to BLOB for all cases in schema.sql, in order to get the scripts to work with MySQL. I can verify that my database is created.
template.setAccessTokenProvider(provider); without this line, I still get the CSRF problems because the resource provider isn't returning the "state" param.
I am using an AuthorizationCodeResourceDetails just like the example as well. I also setup my accessTokenRequest and clientTokenServices identical to the example.
After the user authorizes the client and is redirected back, the code is exchanged for a token and things are working. I can see that my client does have an access token. I expect to see that access token stored in the database as well. I am creating the database schema on startup and the datasource appears to be setup properly. I don't get any errors during runtime that point to configuration issues either. Everything else is working as expected, I just don't get any data in any of the tables where I expect to see information about the access and refresh tokens sent back from the resource server.

Basic auth in DNN Web API service

I'm building a library type module for DNN that will house a Web API service that is meant to be called by a separate application. It has one controller that inherits from DnnApiController. I'd like the requests in this service to use basic auth, since the other app has no association with DNN and its users won't be interacting with the portal. All it can do is pass in a username and password (this will happen over SSL). We are running DNN 7.3 which is configured to use standard Forms authentication.
Is it possible to configure just this service to use basic auth? If so, what attributes/configuration would I need to make it work?
I think you can do this with the DNNAuthorize attribute. First, I would add a role into DNN, example "ExternalApp". Then create a DNN user that has that role.
Make your web service code look like this:
public class MyAPIController : DnnApiController
{
[HttpGet]
[DnnAuthorize(StaticRoles="ExternalApp")]
public string Ping()
{
return "MyAPI Version 01.00.00";
}
}
Then in your external application (let's assume it is written in C#), you can do something like this:
string scheme = "https://";
string domainAlias = "www.website.com";
string modulePath = "myapimodule";
string controllerName = "myapi";
string apimethod = "ping";
Uri serviceUri = new Uri(string.Format("{0}{1}/DesktopModules/{2}/API/{3}/{4}", scheme, domainAlias, modulePath, controllerName, apimethod));
HttpWebRequest httpReq = (HttpWebRequest)HttpWebRequest.Create(serviceUri);
httpReq.Credentials = new NetworkCredential("externalappUser", "password123");
httpReq.Method = "GET";
httpReq.Accept = "application/text";
httpReq.BeginGetResponse(HttpWebRequestCallBack, httpReq);

Multi-tenant logging in ASP.NET MVC application

I have a multi-tenant application in ASP.NET MVC 5 that can accept client logins from multiple companies. Currently, I'm using log4net to log to files, but it places all the logs from all the companies in one file. Ideally, I would like to separate out the log files so that the logs for each company resides in its own folder.
I see from this question that I can programmatically create additional appenders, which then can log to different log files. But that would mean that for each instance of a class, I would have to keep calling
ILog log = LogManager.GetLogger("CompanyA");
to get the correct logger, right? Is there a better way to do so? I'm also open to using another logger if need be.
Thanks.
Do you use an Ioc container in your application? I was able to solve a similar problem using AutoFac MultitenantContainer. Steps that you need to follow
define the strategy you would use to identify each tenant.
Register a generic logger interface with Autofac container
For each tenant register specific logger.
your code could look like (extract from Autofac wiki)
var tenantIdStrategy = new RequestParameterTenantIdentificationStrategy("tenant");
var builder = new ContainerBuilder();
builder.RegisterType<BaseDependency>().As<IDependency>();
// If you have tenant-specific controllers in the same assembly as the
// application, you should register controllers individually.
builder.RegisterType<HomeController>();
// Create the multitenant container and the tenant overrides.
var mtc = new MultitenantContainer(tenantIdStrategy, builder.Build());
mtc.ConfigureTenant("CompanyA",
b =>
{
b.RegisterType<Tenant1Dependency>().As<IDependency>().InstancePerDependency();
b.RegisterType<Tenant1Controller>().As<HomeController>();
});
If this is the only instance where you need to differentiate the tenants and do not want to Ioc at this point you could create the factory like
static class LogFactory
{
public static ILog GetLogger()
{
var requestUri = HttpContext.Current.Request.Url.AbsoluteUri;
switch (requestUri)
{
case "companyA.domain.com":
return LogManager.GetLogger("CompanyA");
case "companyB.domain.com":
return LogManager.GetLogger("CompanyB");
default:
return LogManager.GetLogger("default");
}
}
}
now use the factory instead of directly using Logmanager
ILog logger = LogFactory.GetLogger();

System.DirectoryServices.AccountManagement.UserPrincipal - localhost but not iis

Why does the code below work fine when I run my web application localhost but not when I install it to an IIS server?
using (HostingEnvironment.Impersonate())
{
UserPrincipal activeUser = UserPrincipal.Current;
String activeUserSid = activeUser.Sid.ToString();
String activeUserUPN = activeUser.UserPrincipalName;
}
Please don't suggest I stick with HttpContext.Current.User as it doesn't provide access to SID or UPN without additional calls to Active Directory.
The web application will be used by Windows authenticated users from three separate domains, the web server is hosted in a fourth domain. The Application Pool is configured to run under the NetworkService identity and the web app configuration has identity impersonation set to true.
The error message when it runs on IIS is:
Error in Page_Load(): UserPrincipal.Current.
System.InvalidCastException: Unable to cast object of type
'System.DirectoryServices.AccountManagement.GroupPrincipal' to type
'System.DirectoryServices.AccountManagement.UserPrincipal'.
at System.DirectoryServices.AccountManagement.UserPrincipal.FindByIdentity(PrincipalContext
context, IdentityType identityType, String identityValue)
at System.DirectoryServices.AccountManagement.UserPrincipal.get_Current()
at webapp.Details.Default.Page_Load(Object sender, EventArgs e)
EDIT:
Tried both the following and unfortunately get the same error.
UserPrincipal userPrincipal = UserPrincipal.Current;
Response.Write(userPrincipal.Name);
Principal userOrGroup = UserPrincipal.Current;
Response.Write(userOrGroup.Name);
I had a lot of issues deploying UserPrincipal.Current and still don't fully understand why.
I finally ended up using PrincipalSearcher, and created the following function to do what I thought UserPrincipal.Current was doing.
private UserPrincipal GetActiveDirectoryUser(string userName)
{
using(var ctx = new PrincipalContext(ContextType.Domain))
using(var user = new UserPrincipal(ctx) { SamAccountName = userName})
using(var searcher = new PrincipalSearcher(user))
{
return searcher.FindOne() as UserPrincipal;
}
}
And I passed System.Web.HttpContext.Current.User.Identity.Name into that method as the userName.
It seems like need some other method to determine user.
Here description from msdn for property:
"Gets a user principal object that represents the current user under which the thread is running."
So, UserPrincipal.Current returns user under what IIS running.
http://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.userprincipal.aspx
Yes, its because you are disposing of the returned UserPrincipal object due to the multiple using statements. Remove 'ctx' from the using statement, then it becomes the callers responsibility to dispose of the returned object.

How to get HealthVault to work with multiple ApplicationID in same application

We may never know why Microsoft decided to limit developers by making HealthVault applications constrained to a single web/app.config entry for a HealthVault application. However I need to be able to make 2 (or more) HealthVault ApplicationID’s work with one ASP.NET website? I’m looking for an effective and reliable way to do this.
I won’t go into the details of the reasoning behind 2 different HealthVault applications, but other than to say we need it to work. I still cannot login correctly with MSDN Forums (think infinite redirection sign in loop) so I am hoping for a post here that will help me.
I did contact a HealthVault developer on how to achieve this however the developer gave a suggestion that I don’t believe would be reliable (if I’m wrong let me know).
The developer’s suggestion was to do the following in code when you needed to connect to HealthVault, but prior to connecting:
ConfigurationSettings.AppSettings[“ApplicationId”] = “[YOUR APP ID]”;
The problem is that this is a static property and I do see this as an issue as our web application will have different users accessing both HealthVault applications at the same time.
Does anyone have any suggestions to make 2 (or more) HealthVault ApplicationID’s work with one ASP.NET website? I’m looking for an effective and reliable way to do this.
There is a way to dynamically switch app ids on runtime. Both applications must be created, both certificates must be installed. Few things to keep in mind. For every authenticated connection, user will be granted a token (aka wctoken). This token is consumed when user is redirect back from Live ID (in case live id is used...) by your redirect.aspx page (assuming your redirect page inherits from HealthServiceActionPage.This means that everytime you switch applications, you must redirect user back to Live ID with new app id to receive new token.
Here is code sample that can be user to dynamically change settings:
public class ConfigurationManager : HealthWebApplicationConfiguration
{
private string appid;
public ConfigurationManager(string appid)
{
this.appid = appid;
}
public override Guid ApplicationId
{
get
{
return AppManager.Current.GetCurrentAppId(this.appid);
}
}
}
public class AppManager
{
private static readonly Object lck = new Object();
public Guid? App;
public static AppManager Current
{
get
{
AppManager mgr = null;
if (_current == null)
{
lock (lck)
{
mgr = new AppManager();
}
}
return mgr;
}
}
private static AppManager _current;
public Guid GetCurrentAppId(string id)
{
return new Guid(id);
}
}
Usage:
ConfigurationManager cm = new ConfigurationManager(your-app-id-here);
HealthWebApplicationConfiguration.Current = cm;

Resources