Basic auth in DNN Web API service - asp.net

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);

Related

What settings to use in ADAL to access Azure AD

I am using below settings in ADAL to access Azure AD.
this is settings someone used and I found in internet
public const string ApplicationId = "your-application-id";
public const string ReturnUri = "http://your-uri.com/";
public const string Authority = "https://login.windows.net/common";
public const string GraphResourceUri = "https://graph.windows.net";
this is my setting
public static string ApplicationID = "xxxx-xxxx-xxxx-xxxx-xxxxx";
public static string ReturnUri = "http://myAppName register in AzureAD";
public static string tenanturl = "https://login.microsoftonline.com/xxx-xxx-xxx-xxx-xxx";
public static string GraphResourceUri = "https://graph.microsoft.com";
Problem:
I hope someone can confirm the following:
a) Is Authority is same as tenanturl ? which one to use: login.windows.net or login.microsoftonline.com
b) which to use for GrapResourceUri: graph.windows.net or graph.microsoft.com
c) are the settings in 1 and 2 complete? or there is more settings to add.
d) the token return from Azure AD is SAML or JWT token?
a) Is Authority is same as tenanturl ? which one to use: login.windows.net or login.microsoftonline.com
Authority should be https://login.microsoftonline.com/your-tenant-id-here.
You can use either the unique id for your AAD tenant or one of the verified domain names, e.g. https://login.microsoftonline.com/mytenant.onmicrosoft.com.
b) which to use for GrapResourceUri: graph.windows.net or graph.microsoft.com
If you want to call Azure AD Graph API, the first. If you want to call Microsoft Graph API, you use the second.
c) are the settings in 1 and 2 complete? or there is more settings to add.
Sadly the answer is it depends.
There are many flows for acquiring an access token in Azure AD, and which one you use (and thus which overload of AcquireAccessToken() you use) depends on the type of your application and what is the situation.
The settings here are enough for a native application (which yours is I guess since the Xamarin Forms tag is there).

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.

Winform calling ASP.NET Web API with Claims

I have a Winform client that we are slowing changing inline SQL data calls into ASP.NET Web API calls. We currently use the WindowsPrincipal.IsInRole check in the Winform client to determine if the user can run the SQL data calls. We would like to move into a Claims type setup where both the Winform client and the Web API can check the roles "claims" of a user.
I can't seem to find any "good" articles on how to get a Winform client to (1. Pass the claim to the service) and (2. Use a claim check inside the Winform client like the IsInRole). Any help or push in the right direction would be great.
--EDIT
So I used this article http://zamd.net/2012/05/04/claim-based-security-for-asp-net-web-apis-using-dotnetopenauth/ as a sample on getting a token back from the server but the article does not show how to get the claims identity out of the http client. Any idea how to get the claims identity out of the http client?
While I haven't tested this code, hopefully it will get you moving in the right direction.
I believe to answer your question you do this in your ClaimsAuthenticationManager where upon validating the token received from the server you set the Thread.CurrentPrincipal -- the same way you do on the web side without setting the HttpContext.Current.User principal.
Again this isn't tested but I think it would look something like this...
In my Token Validator I have the following code:
public static ClaimsPrincipal ValidateToken(string token)
{
var tokenHandler = new JwtSecurityTokenHandler();
ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(new JwtSecurityToken(token),
Constants.TokenValidationParameters);
return FederatedAuthentication.FederationConfiguration
.IdentityConfiguration
.ClaimsAuthenticationManager.Authenticate(token, claimsPrincipal);
}
public static string GetToken(string username, string password)
{
OAuth2Client client = Constants.OAuth2Client;
AccessTokenResponse response = client.RequestAccessTokenUserName(username.ToLower(), password,
Constants.AllowedAudience);
return response.AccessToken;
}
Within my ClaimsAuthenticationManager I have modified the following code as you don't want to set the HttpContext in a non web environment:
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (!incomingPrincipal.Identity.IsAuthenticated)
{
return base.Authenticate(resourceName, incomingPrincipal);
}
/* HttpContext.Current.User = */ Thread.CurrentPrincipal = incomingPrincipal;
return incomingPrincipal;
}
I believe you then just have to set the appropriate keys in the app.config, specifically the system.identityModel => identityConfiguration => claimsAuthenticationManager
Once the thread you are running on has the "Authenticated Principal" you should be able to call the ClaimsPrincipal.Current.HasClaim() or your higher level Authorization.CheckAccess() function to validate sections of your WinForm logic.
Hope this helps :)

When ApplicationID is generated in Membership.CreateUser method?

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.

Custom IPrincipal together with WindowsAuthentication

Is there any good way of combining ASP.NET Windows Authentication with a custom IPrincipal/IIdentity object? I need to store the user's email address and have done so for Forms Authentication using a custom IIdentity/IPrincipal pair that I added to the Context.CurrentUser during the AuthenticateRequest event.
How would I best go by to accomplish this using WindowsAuthentication?
Maybe you could create your "ExtendedWindowsPrincipal" as a derived class based on WindowsPrincipal, and just add your extra data to the derived class?
That way, your ExtendedWindowsPrincipal would still be recognized anywhere where a WindowsPricinpal is needed.
OR: since you're talking about using Windows Authentication, you're probably in a Windows network - is there an Active Directory or a user database somewhere, where you could look up your e-mail address that you're interested in instead of storing it in the principal?
Marc
I ended up refactoring my initial solution into replacing the Principal instead of the Identity as I originally thought. Replacing the Identity proved troublesome, since i ran into security problems when creating an instance of a new extended WindowsPrincipal.
public class ExtendedWindowsPrincipal : WindowsPrincipal
{
private readonly string _email;
public ExtendedWindowsPrincipal(WindowsIdentity ntIdentity,
string email) : base(ntIdentity)
{
_email = email;
}
public string Email
{
get { return _email; }
}
}
In my Authentication module i replaced the principal on the HttpContext like this:
var currentUser = (WindowsIdentity)HttpContext.Current.User.Identity;
HttpContext.Current.User =
new ExtendedWindowsPrincipal(currentUser, userEmail);

Resources