In my first project going real DDD, I'm stuck with some doubts concerning which course to take in this scenario...
I have a distributed architecture, in which users of several applications will have only one account that will make them able to authenticate. This account can be created on our own system, or the user can share with us his login with facebook, google and other third-party account provider.
So, there's a project for only this purpose, control user accounts.
This scenario made me came with this approach within my model (simplified):
public class User
{
public User(string name)
{
Id = Guid.NewGuid();
Name = name;
}
public Guid Id { get; protected set; }
public string Name { get; protected set; }
}
public abstract class Account
{
protected Account(User user)
{
Id = Guid.NewGuid();
User = user;
}
public Guid Id { get; protected set; }
public User User { get; protected set; }
}
public class MySystemAccount : Account
{
public MySystemAccount(string email, string password, User user)
: base(user)
{
Email = email;
Password = password;
}
public string Email { get; protected set; }
public string Password { get; protected set; }
}
public class FacebookAccount : Account
{
public FacebookAccount(string facebookId, User user)
: base(user)
{
FacebookId = facebookId;
}
public string FacebookId { get; protected set; }
}
The thing is that the other applications will access this project via REST services.
So, I thought about a single /Authenticate service that will provide a json with dynamic form. It could de a json with a email/password, or a json with the facebookId.
But then, how can I connect the layers?
I thought about making an application service, but I got stuck on who and how should decide what is going on, what should my rest service communicate to the application and how the application will know to do the thing, whatever kind of authentication it is, an user from my own domain or a user from facebook and so on..
Any thoughts on this?
Thanks!
This seems to be a multi-part question - one part about the object model and polymorphism and another about architecture.
Regarding the object model, the use of inheritance isn't ideal in this scenario. Each sub-type of Account won't really have much specific behavior or any behavior at all. The only specialization is the presence of different data fields. Additionally, use of inheritance will complicate persistence.
Architecturally, what I think you're trying to achieve is federated identity. This basically decouples the notion of a user (an identity) from the authentication process. In turn, this allows all remaining application code to bypass authentication concerns and depend only on the user's identity. Take a look at OpenID as well as the DotNetOpenAuth library which provides an OpenID implementation in C#.
I'm new to Stackoverflow, so not sure how to just put this as a "suggestion", but I would rethink your model a little bit. I think of a "User" as someone who strictly is a person utilizing your application through your own website. This "User" would go through the authentication as you suggested, either via an account from your own system, or via an Open ID or OAuth ID provider like Facebook and Google.
If an application however, wants to access your "application" via REST calls, then I'd put them through a different authentication mechanism. In a sense to me, you are providing an API layer and software as a service. I'd take a look at how Twitter, Facebook, or Google expose their APIs for other applications to use. Typically, there is a secret key and application ID involved in authenticating the REST calls.
Related
I am in need of help with Web Api.
I am setting up a multi tenant system when each tenant has there own database of data using code first EF and web api (so that I can create multiple app platforms)
I have extended the standard ASP.NET Identity to include a client id and client model which will store all tenants and their users.
I have then created another context which tracks all the data each tenant stores.
Each tenant holds a database name which I need to access based on the authenticated user.
Not getting the user id from each api controller seems easy:
RequestContext.Principal..... etc then I can get the client and subsequently the client database name to pass to the database context however I am trying to implement a standard data repository pattern and really hate repeating myself in code yet the only way I see it working at the moment is to:
Application calls restful api after authorisation
Web Api captures call
Each endpoint gets the user id and passes it to the data store via the interface and subsequently into the data layer retrieving the database name for the context.
What I have a problem with here is each endpoint getting the user id. Is there a way to "store/track" the user id per session? Can this be achieved through scope dependency or something similar?
I hope that makes sense but if not please ask and I will try to clarify further, any help will be greatly appreciated.
Thanks
Carl
ASP WebApi does not have a session context. You may use a cookie or a request token identifier (pass this token back from login and use this token as a parameter for further API calls).
This is something I've developed some time ago. I'm simply creating a new class deriving from ApiController and I'm using this class as a base for all other API class. It is using the ASP.NET cache object which can be accessed via HttpContext. I'm using the current user-id as a reference. If you need something else, you may use another way of caching your data:
public abstract class BaseController: ApiController
{
private readonly object _lock = new object();
/// <summary>
/// The customer this controller is referencing to.
/// </summary>
protected Guid CustomerId
{
get
{
if (!_customerId.HasValue)
{
InitApi();
lock (_lock)
{
if (User.Identity.IsAuthenticated)
{
Guid? customerId = HttpContext.Current.Cache["APIID" + User.Identity.Name] as Guid?;
if (customerId.HasValue)
{
CustomerId = customerId.Value;
}
else
{
UserProfile user = UserManager.FindByName(User.Identity.Name);
if (user != null)
{
CustomerId = user.CustomerId;
HttpContext.Current.Cache["APIID" + User.Identity.Name] = user.CustomerId;
}
}
}
else
{
_customerId = Guid.Empty;
}
}
}
return _customerId.GetValueOrDefault();
}
private set { _customerId = value; }
}
// ... more code
}
Do not blame me on the "lock" stuff. This code was some kind of "get it up and running and forget about it"...
A full example can be found here.
Maybe I am far from truth but Web API is state less so you dont really have a session to track
My question involves both a technical and a modeling issue.
I have a MCV 5 system where there will be a web front-end and also a mobile app(Android).
At some point the web user will be able to see a queue of mobile signed-on users.
Mobile accounts wont access web front-end neither web accounts the mobile app.
I have chosen Azure to provide all my system needs.
Modeling wise, should I create separate login systems(one more backend system for mobile login)?
If not, is the Asp.net Identity system capable of using two different logins, as I tought roughly something like this:
namespace Application.Models {
// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
public virtual ICollection<ApplicationMobileClient> Clients { get; set; }
}
public class ApplicationMobileClient : IdentityUser
{
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}
}
}
The web user model would have a collection of mobile clients model. Just like an photo/comments system. But I dont know(well I asume not) if the Identity can do something like this, handle two logins on same application. I could Maybe im just larning too much technologies/frameworks/metodologies/patters at the same time and Im just dont know what to do lol.
I can't see why you should need two different ApplicationUser. Because it's the same user regardless if he is on your website or signed in through your Android app. If you want to keep track of the users mobile sign ins then you can add a property to the ApplicationUser.
public class ApplicationUser : IdentityUser
{
public virtual ICollection<MobileSignIn> MobileSignIns { get; set; }
}
public class MobileSignIn
{
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection")
{ }
}
I have an Asp.Net MVC 5.1 website. We've got 3 types of users and I want to add support for chat between one type of them. I have thought of some models like this:
public class Conversation
{
public NormalUser A { get; set; }
public NormalUser B { get; set; }
public List<PrivateMessaage> Messages { get; set; }
}
public class PrivateMessaage
{
public NormalUser Sender { get; set; }
public NormalUser Receiver { get; set; }
public string Message { get; set; }
public DateTime Created { get; set; }
}
Also, I'm using SignalR in other parts of the project and thought like it's a very good solution to add the chat interface on top of the SignalR. Everything looks good so far. However, I think hitting the database to insert a new message EVERY time a message is being typed is not a good idea. I've created so many strategies to implement custom donut caching in my website to make every single page as fast as possible and it seems like this would cancel all of them out! What is the preferred solution to this problem? I think I might take some approaches like these:
Push them to the database in batches. For instance once a message is past a threshold (its date/time difference is more than X or the message count is more than Y).
Don't support offline messages, just push them in-memory to the other side through SignalR.
Same as the 2nd, but support offline when the target user is offline. I imagine not many messages will be sent to offline users!
Don't cache anything. I'll work out!!
One issue with the first one is that, there might be a situation where the website would go down (for update, power failure, apocalypse(!), etc.) and all the messages in memory would be lost. I can add a custom action to flush everything but it's never quite safe. Since there's a lot of chat solutions out there, I think there are very convenient solutions to this.
If you are not opposed to using other databases, realtime chat is extremely easy using Firebase and AngularJS.
An app I'm working on interfaces with an existing application running on a remote box. Communicaitons with the remote app are via its public web services. I've been asked to build an enhancement which will involve a client making use of the web service to handle sensitive data which will need to be transmitted securely.
Could anyone give me some pointers on how best to proceed?
To start, you should be using SSL and reject any requests that are not using it. This will encrypt data as it's being transmitted over the Internet.
If you are using SOAP, you could define a custom header in your service that takes a username / password. Then, for the first line in each public method, validate the username and password against a database. If successful, set the HttpContext.Current.User appropriately, and your service will tie in nicely with the built in Asp.NET infrastructure.
ADDED: Below is a sample SoapHeader that includes a username / password for authentication.
// define the header
public class AuthenticationHeader : SoapHeader
{
public String UserName { get; set; }
public String Password { get; set; }
}
// your service
public class PublicWebService : WebService
{
// defines an instance of the header as part of the service
public AuthenticationHeader Authentication;
private void Authenticate()
{
// validate the username / password against a database
// set the HttpContext.Current.User if successful.
// Maybe throw a SoapException() if authentication fails
}
// Notice the SoapHeader("Authentication") attribute...
// This tells ASP.Net to look for the incoming header for this method...
[WebMethod]
[SoapHeader("Authentication")]
public void PublicMethod1()
{
Authenticate();
// your code goes here
}
// Expose another method with the same authentication mechanism
[WebMethod]
[SoapHeader("Authentication")]
public void PublicMethod2()
{
Authenticate();
// your code goes here
}
}
Now, if you run the wsdl tool, the generated proxy class will include the defined authentication header:
PublicWebService s = new PublicWebService();
s.Authentication = new AuthenticationHeader();
s.Authentication.UserName = "xxxxxxxx";
s.Authentication.Password = "yyyyyyyy";
s.PublicMethod1();
s.PublicMethod2();
DIY route:
Read up on security (start with "Secrets and Lies" and other such general books before moving on to the technicalities)
Perform a risk analysis and thread assessment. Understand what you are protecting and from what, and where threats will come from. You are unlikely to need "High Security"1.
Use TLS (aka SSL).
In the client, verify the server's certificate is correct.
Better route: employ an expert who has an established reputation to help you.
1 Unless you really are building a nuclear weapons plant or similar.
I am in the process of looking at an API and I see the following two calls:
API.Users.Roles.getAllRoles();
API.Admin.Roles.getAllRoles();
What I would like to know is how each of these call is used within
the context of a Web program. Since both Admin and Users are properties,
what exactly is the get; set; doing? How does the call know which Admin
(or user) is making the call?
My hunch is that this has something to do with how the API class is
instantiated (and session?) but I'd appreciate a walk-through on what is
going on here so I fully understand it.
The (abbreviated) class structure looks like the following:
public class API()
{
public Admin Admin { get; private set; }
public Users Users { get; private set; }
}
public class Users
{
public Roles Roles { get; private set; }
...
}
public class Roles
{
public override string[] GetAllRoles()
{
...
}
}
Thanks in advance.
It will check the current user name from the current principal (HttpContext.Current.User.Identity.Name) which uses forms/windows account depending on setup, or if not in the web environment, it will use the current windows user logged into the system.
To me it seems that they have a custom role provider and are therefore overriding the GetAllRoles method so that the roles can be obtained from the datasource. Without seeing further details, I can only assume, but when a user registers, they're probably assigned a particular role. They can then use the Roles.IsUserInRole method to detect what role the user is assigned to. There's more on custom role providers here which will explain why methods are being overwritten.