ADAM and Azman with ASP.Net forms authentication - asp.net-membership

Has anyone been able to make ADAM/Azman work with ASP.Net forms authentication. The default ADAM role provider works only with AD Domain users. And every single article I have read says that you need to write a custom role provider for it.
I have also found out bits and pieces of custom role provider code here and there, but nothing concrete. If someone can share the roleprovider needed for this, that will be great.
I have followed following articles so far :
Custom Role provider (doesn't work) - http://www.codeproject.com/KB/aspnet/active_directory_roles.aspx
Partial Custom Role provider code - http://blogs.msdn.com/b/azman/archive/2006/05/06/591230.aspx
Partial Custom Role provider code again - http://blog.avanadeadvisor.com/blogs/johanr/archive/2009/01/20/12373.aspx
MS Article steps to setup ADAM and use it with ASP.Net (windows auth)
Getting started with ADAM for authentication (no roles) - http://www.alexthissen.nl/blogs/main/archive/2007/07/26/getting-started-with-adam-and-asp-net-2-0.aspx

I have a hacked version, and I seriously mean hacked. I don't need to modify roles in my app, so I only implemented 2 methods. I had to send a username and password to query the directory. Someday I'd like to figure out how to use the ActiveDirectoryMembershipProvider's connection string, but I did not spend a lot of time with it, that would simplify things.
public class ActiveDirectoryFormsRoleProvider : RoleProvider
{
public string DomainController { get; set; }
public string ConnectionLDAPSuffix { get; set; }
public string ConnectionUserName { get; set; }
public string ConnectionPassword { get; set; }
public override string ApplicationName { get; set; }
public override bool IsUserInRole(string username, string roleName)
{
var roles = GetRolesForUser(username);
return roles.Contains(roleName);
}
public override string[] GetRolesForUser(string username)
{
var results = new List<string>();
using (var context = new PrincipalContext(ContextType.Domain, DomainController,ConnectionLDAPSuffix,ConnectionUserName,ConnectionPassword))
{
try
{
var p = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);
//looping twice because I was getting AppDomainUnloadedException on 50% of the first attempts
for (var i = 0; i < 2; i++)
{
try
{
var groups = p.GetAuthorizationGroups();
foreach (GroupPrincipal group in groups)
{
var name = group.SamAccountName;
if (!string.IsNullOrWhiteSpace(name))
results.Add(group.SamAccountName);
}
break;
}
catch (AppDomainUnloadedException)
{
}
}
}
catch (Exception ex)
{
throw new ProviderException("Unable to query Active Directory.", ex);
}
}
return results.ToArray();
}
...
For some reason on my production server, I have to make 2 attempts of GetAuthorizationGroups() because 50% of the time the first attempt failed by throwing AppDomainUnloadedException. You might be able to remove that for loop.
And here is my web.config element:
<roleManager enabled="true" defaultProvider="ActiveDirectoryFormsRoleProvider">
<providers>
<clear />
<add name="ActiveDirectoryFormsRoleProvider"
type="myapp.ActiveDirectoryFormsRoleProvider"
applicationName="myapp"
DomainController="domaincontroller.testdomain.corp"
ConnectionLDAPSuffix="DC=testdomain,DC=corp"
ConnectionUsername="username"
ConnectionPassword="password"
/>
</providers>
</roleManager>

Related

How do I get WorkFlowActivityBase class in Visual Studio?

I am creating a custom workflow in Microsoft Dynamics CRM to automatically update a field when a record is saved.
A developer on a forum provided the following source code; but he is not responding to my questions.
public class SalesRepActivity2 : WorkFlowActivityBase
{
[Input("Sales Rep Name")]
public InArgument<string> SalesRepName { get; set; }
[Output("Sales Rep")]
[ReferenceTarget("systemuser")]
public OutArgument<EntityReference> SalesRep { get; set; }
[Output("IsSuccess")]
public OutArgument<bool> IsSuccess { get; set; }
[Output("Message")]
public OutArgument<string> Message { get; set; }
protected override void Execute(
CodeActivityContext activityContext,
IWorkflowContext workflowContext,
IOrganizationService CrmService,
ITracingService trace)
{
try
{
string salesRepName = SalesRepName.Get(activityContext);
if (string.IsNullOrWhiteSpace(salesRepName))
{
IsSuccess.Set(activityContext, false);
Message.Set(activityContext, "Sales Rep Name not provided");
}
var QEsystemuser = new QueryExpression("systemuser");
QEsystemuser.ColumnSet.AddColumns("salesrepname");
QEsystemuser.Criteria.AddCondition("salesrepname", ConditionOperator.Equal, salesRepName);
var results = CrmService.RetrieveMultiple(QEsystemuser);
if (results == null || !results.Entities.Any())
{
IsSuccess.Set(activityContext, false);
Message.Set(activityContext, "User with " + salesRepName + " not found");
return;
}
if (results.Entities.Count > 1)
{
IsSuccess.Set(activityContext, false);
Message.Set(activityContext, "Multiple users found with same name : " + salesRepName);
return;
}
IsSuccess.Set(activityContext, true);
SalesRep.Set(activityContext, results.Entities.Single().ToEntityReference());
}
catch (Exception ex)
{
IsSuccess.Set(activityContext, false);
Message.Set(activityContext, "An error occurred trying to find user : " + ex.Message);
}
}
I am trying to get the code to compile on my machine.
I installed the following NuGet packages, which resolved most of the errors:
Microsoft.Xrm.Sdk.Workflow.2015
Microsoft.Xrm.Sdk.2015
But my project cannot resolve the WorkFlowActivityBase class.
Is there a reference I should set or a NuGet package I should install to resolve this?
Thank you.
WorkFlowActivityBase is a custom base class that implements the CodeActivity (System.Activities) anyone can write, it's not an official Dynamics class. Yon can find dozen of classes lie that in the web.
Basically, you should use the CodeActivity. here as an example:
https://learn.microsoft.com/en-us/powerapps/developer/common-data-service/workflow/sample-create-custom-workflow-activity
The code you posted is not a good place for you to start because it makes heavy use of proprietary objects. Ziv has provided good information about extending the CodeActivity class but I do not recommend starting there. Instead read about how to develop custom workflow activities, and write a workflow using the base Microsoft classes so that you understand how they work:
https://learn.microsoft.com/en-us/powerapps/developer/common-data-service/workflow/workflow-extensions
Once you have some experience with creating custom workflows, and you understand the limitations of the base objects, then go back and implement something more fancy.
Here in an exaple from the documentation:
namespace Microsoft.Crm.Sdk.Samples
{
public sealed class SimpleSdkActivity : CodeActivity
{
protected override void Execute(CodeActivityContext executionContext)
{
//Create the tracing service
ITracingService tracingService = executionContext.GetExtension<ITracingService>();
//Create the context
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
...
var systemUsers = service.RetrieveMultiple(QEsystemuser)
}
}
}

Login via Xamarin Forms Application

we have an mvc 5 application with individual user authentication we also have a xamarin forms application. we need to be able to use the same login details thats created on the web application when we log in via the xamarin application we are creating. we have successfully been able to create web api controllers using existing models in the web application and read/write the data in the xamarin application. but the problem is that we are not able to provide the same authentication we have(username and password with role assigned to the user) to the xamarin application. how can we make an api controller that reads from our existing database..please note our application is hosted on azure with a sql database.
basically we want to provide a login to our web application via the mobile app.
You need to take a look at Adrian Halls book - chapter 2 covers custom authentication which is what you need.
https://adrianhall.github.io/develop-mobile-apps-with-csharp-and-azure/chapter2/custom/
The key points are setting the mobile app to use authentication in the Azure portal but don't set any of the authentication providers (this makes it custom)
You then need to implement your own custom authentication controller to handle the authentication call back like this example taken from Adrian's book;
using System;
using System.IdentityModel.Tokens;
using System.Linq;
using System.Security.Claims;
using System.Web.Http;
using Microsoft.Azure.Mobile.Server.Login;
using Newtonsoft.Json;
namespace AWPBackend.Controllers
{
[Route(".auth/login/custom")]
public class CustomAuthController : ApiController
{
private MobileServiceContext db;
private string signingKey, audience, issuer;
public CustomAuthController()
{
db = new MobileServiceContext();
signingKey = Environment.GetEnvironmentVariable("WEBSITE_AUTH_SIGNING_KEY");
var website = Environment.GetEnvironmentVariable("WEBSITE_HOSTNAME");
audience = $"https://{website}/";
issuer = $"https://{website}/";
}
[HttpPost]
public IHttpActionResult Post([FromBody] User body)
{
if (body == null || body.Username == null || body.Password == null ||
body.Username.Length == 0 || body.Password.Length == 0)
{
return BadRequest(); ;
}
if (!IsValidUser(body))
{
return Unauthorized();
}
var claims = new Claim[]
{
new Claim(JwtRegisteredClaimNames.Sub, body.Username)
};
JwtSecurityToken token = AppServiceLoginHandler.CreateToken(
claims, signingKey, audience, issuer, TimeSpan.FromDays(30));
return Ok(new LoginResult()
{
AuthenticationToken = token.RawData,
User = new LoginResultUser { UserId = body.Username }
});
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool IsValidUser(User user)
{
return db.Users.Count(u => u.Username.Equals(user.Username) && u.Password.Equals(user.Password)) > 0;
}
}
public class LoginResult
{
[JsonProperty(PropertyName = "authenticationToken")]
public string AuthenticationToken { get; set; }
[JsonProperty(PropertyName = "user")]
public LoginResultUser User { get; set; }
}
public class LoginResultUser
{
[JsonProperty(PropertyName = "userId")]
public string UserId { get; set; }
}
The actual custom authentication takes place in the IsValidUser function and should link to your existing internal authentication method (do not use the example here, this is for demonstration only)
Custom authentication has to use a client side flow which also meets your requirements.

fetch data from server using xamarin with realm

I am trying to create mobile app using Xamarin and Realm. I am trying to pull data from server and load it into objects extended by RealmObjects.
code to fetch data from server
public async void getCompanyMaster() {
var uri = new Uri(string.Format(URL, string.Empty));
try
{
getConnection();
var response = await client.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
Company company = JsonConvert.DeserializeObject<Company>(content);
Debug.WriteLine("Company List " );
}
}
catch (Exception e)
{
Debug.WriteLine("Error {0}", e.Message);
}
}
realm model company
namespace DesignModel.Model.Master
{
public class Company : RealmObject
{
public string errorMessage { get; set; }
public string status { get; set; }
[JsonProperty(PropertyName = "companyMaster")]
IList<CompanyMaster> companyMaster { get; }
}
}
realm model for company master
namespace DesignModel.Model.Master
{
public class CompanyMaster : RealmObject
{
public string companyAddress { get; set; }
public string companyId { get; set; }
public string companyName { get; set; }
public string companyPhoneNumber { get; set; }
}
}
now the issue is at following line in getCompanyMaster function
Company company = JsonConvert.DeserializeObject<Company>(content);
it raises an exception
Error Error setting value to 'errorMessage' on
'DesignModel.Model.Master.Company'.
if i do not extend my class from RealmObject then it works fine but when i add RealObject it doesn't work.
the above approach does work in android native but do not know why it doesn't work in xamarin.
sample json
{
"errorMessage": "",
"status": "Ok",
"companyMaster": [
{
"companyAddress": "123 Coffee Street\nSuite 300\nRedmond, WA 98052\nUSA",
"companyId": "cec",
"companyName": "Contoso Entertainment Systems",
"companyPhoneNumber": "425-555-0156"
}]
}
complete stack trace
[0:] Error Newtonsoft.Json.JsonSerializationException: Error setting
value to 'errorMessage' on 'DesignModel.Model.Master.Company'. --->
System.PlatformNotSupportedException: The PCL build of Realm is being
linked which probably means you need to use NuGet or otherwise link a
platform-specific Realm.dll to your main application.
Adding a note from documentation found here
https://realm.io/docs/xamarin/latest/
under Getting Started - Prerequisites
Important note for PCL users - this works via the NuGet Bait and Switch
Trick. You
have to install the Realm NuGet package into every PCL that uses Realm
as well as each of your platform-specific projects, e.g.: your final
app for iOS and Android. If you are using shared projects, you only
have to install the NuGet into each platform-specific project.

Oracle EF 6 Code first: How to secure the password field in the connection string in app.config

I am developing an Windows application with Oracle EF 6 Code first. It works fine, however, the password is stored as a plain text in the connection string in app.config:
<connectionStrings>
<add name="OracleDbContext" providerName="Oracle.ManagedDataAccess.Client" connectionString="User Id=UsrName;Password=password;Data Source=ds" />
</connectionStrings>
What is the best practice to secure the password? I tried to load the connection string and provide the password at run time. Then pass the whole connection string to DBContext via constructor:
public class OracleDbContext : DbContext
{
public OracleDbContext(string connectionstring)
:base(connectionstring)
// : base("name=OracleDbContext")
{
}
...
}
}
public OracleDbContext CreateDbContext()
{
ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["OracleDbContext"];
string connectString = settings.ConnectionString;
OracleConnectionStringBuilder builder = new OracleConnectionStringBuilder(connectString);
if (String.IsNullOrEmpty(builder.Password))
{
builder.Password = "password";
}
return new OracleDbContext(connectString);
}
but, It failed with an error "Unable to complete operation. The supplied SqlConnection does not specify an initial catalog or AttachDBFileName."
In this MSDN article you will find some information about encrypting connection strings inside web.config / app.config.
I use this way to separate the connectionstring for user.config, but this can easy be tweaked for inserting user/pwd in runtime.
<appSettings file="user.config">
<add key="db" value="DATA SOURCE=server:1521/instance;PASSWORD=password;PERSIST SECURITY INFO=True;USER ID=user"/>
public static string CreateEFConnectionString()
{
var connectionString = ConfigurationManager.AppSettings["db"];
var builder =
new EntityConnectionStringBuilder(
"metadata=res://*/EF_Model.csdl|res://*/EF_Model.ssdl|res://*/EF_Model.msl;provider=Oracle.ManagedDataAccess.Client;")
{
ProviderConnectionString = connectionString
};
return builder.ConnectionString;
}
using (var en = new Entities(Dbutils.CreateEFConnectionString()))
{}
.
public Entities() : base("name=Entities")
{
}
public Entities(string connectionstring) : base(connectionstring)
{
this.Configuration.LazyLoadingEnabled = true;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
}

ASP.NET MVC 3 - Unit Test in Respository

I'm using a class test that checks login entity that is being done correctly, but an error occurs that does not seem to return the query in the database, but the application developed in ASP.NET MVC 3 Code First query returns data, I would to know what is wrong and what can be done to solve it.
Upon return of the query gives the following message in the variable:
"Enumeration yielded no results"
Test Method:
[TestMethod()]
public void efetuarLoginTest()
{
EntidadeRepository target = new EntidadeRepository();
string cnpj = "12345678";
string senha = "lalado";
Entidade expected = null; // TODO: Initialize to an appropriate value
Entidade actual;
actual = target.efetuarLogin(cnpj, senha);
Assert.AreNotEqual(expected, actual);
}
Method repository of the entity with the task of returning to the login query:
public Entidade efetuarLogin(string cnpj, string senha)
{
var consulta = from usu in bd.Entidades
where usu.cnpj == cnpj && usu.senha == senha
select usu;
if (consulta.Count() > 0)
{
Entidade e = new Entidade();
e.id_entidade = consulta.First().id_entidade;
e.razao_social = consulta.First().razao_social;
e.cnpj = consulta.First().cnpj;
e.senha = consulta.First().senha;
return e;
}
else
{
return null;
}
}
Class persistence database using the Entity Framework 4.1:
internal class BancoDados: DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingEntitySetNameConvention>();
modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
public DbSet<Entidade> Entidades { get; set; }
public DbSet<Estado> Estados { get; set; }
public DbSet<Administrador> Administradores { get; set; }
public DbSet<Leilao> Leiloes { get; set; }
public DbSet<Lance> Lances { get; set; }
}
Thank You.
for us, this kind of an error was generated because of the right connection string not passed to the EF. If you are using NUnit, NUnit doesn't use your app.config or web.config, you would have to create your assembly.dll.config or nunit project.config. Please check NUnit documentation for usage of config files.
You can verify the connection string passed to NUnit, by examining, DbContext.Database and its properties in debug mode/
Checking your config values, should fix your problem.
I would imagine
if (consulta.Count() > 0)
is throwing the error?
You could change it to
if (consulta != null && consulta.Count() > 0)

Resources