Hi guys i m making one asp.net project with silverlight2.0 .But i cannot get current user name... how can i get current user name
thanks...
I basically handle this in one of two ways.
1) Use the ASP.NET Silverlight control. When the server control loads, grab the current user name using HttpContext.Current.User.Identity.Name and send it in as an InitParam into the silverlight control.
2) I generally only need the user name when I call back to the server. If the service requires windows authentication, you can just call HttpContext.Current.User.Identity.Name inside the service to get the user name
Basically, you need to implement a service that will return current user info to the client and call this service on Silverlight application startup.
The example of the service:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class UserInfoService : IUserInfoService
{
public UserInfo GetUserInfo()
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
return null;
var userInfo = new UserInfo
{
Login = HttpContext.Current.User.Identity.Name,
Fullname = ...,
};
return userInfo;
}
}
Related
I followed the quickstart here: https://learn.microsoft.com/en-us/powerapps/developer/common-data-service/webapi/enhanced-quick-start
Which worked great, so then I need to register my app, so I followed this:
https://learn.microsoft.com/en-us/powerapps/developer/common-data-service/walkthrough-register-app-azure-active-directory
But now my unit tests give me the error:
Microsoft.IdentityModel.Clients.ActiveDirectory.AdalServiceException:
AADSTS65001: The user or administrator has not consented to use the
application with ID '[GUID]' named '[AppName]'. Send an interactive
authorization request for this user and resource.
I feel like I understand the error, that the administrator needs to consent. My program is doing some magic in the bakcgorund and the user is not signing in, it is using a set username and password and the user should not be consenting to anyone. Is there any way to set this consent permanently, or force it every time through the Helper class in the first tutorial? All my Google-fu came up empty... Thank you.
You can use something like this:
CrmserviceClient is from Microsoft.Xrm.Tooling.Connector nuget
private CrmServiceClient GenerateService()
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
ServicePointManager.Expect100Continue = true;
ServicePointManager.CheckCertificateRevocationList = true;
ServicePointManager.DefaultConnectionLimit = 10;
var service = new CrmServiceClient(new Uri(organizationUrl), clientId, secret, false, string.Empty);
if (service.IsReady == false)
{
throw new Exception("CrmOrgService isn't ready. " + service.LastCrmError);
}
return service;
}
Or if you want to use connection string you can use this:
Connection string : https://learn.microsoft.com/en-us/dynamics365/customerengagement/on-premises/developer/xrm-tooling/use-connection-strings-xrm-tooling-connect
var connectionString =
ConfigurationManager.ConnectionStrings["XY"].ConnectionString;
var conn = new CrmServiceClient(connectionString);
IOrganizationService orgService = conn.OrganizationServiceProxy;
I would like to make the login page know which client requested the login in order to display some client-specific branding: Otherwise the user may be confused as to why he's redirected to this foreign login page on a different domain. A client logo will help reassure him that he's still on the right track.
What would be the most reasonable approach to get at that information?
EDIT: Note that by "client" I'm referring to the client web applications on whose behalf the authentication happens - not the user's browser. All clients are under my control and so I'm using only the implicit workflow.
To make this even more clear: I have client web apps A and B, plus the identity server I. When the user comes to I on behalf of B, the B logo should appear as we're no longer on B's domain and that may be confusing without at least showing a B-related branding.
Some Theory
The easiest way to get the ClientId from IdSrv 4 is through a service called IIdentityServerInteractionService which is used in the Account Controller to get the AuthorizationContext. And then follow that up with the IClientStore service that allows you to get the client details given the ClientId. After you get these details then its only a matter of sending that info to the view for layout. The client model in IdSrv 4 has a LogoUri property that you can utilize to show an image at login per client.
Simple Example
// GET: /Account/Login
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> Login(string returnUrl = null)
{
var context = await _interaction.GetAuthorizationContextAsync(returnUrl);
if (context?.IdP != null)
// if IdP is passed, then bypass showing the login screen
return ExternalLogin(context.IdP, returnUrl);
if(context != null)
{
var currentClient = await _clientStore.FindClientByIdAsync(context.ClientId);
if (currentClient != null)
{
ViewData["ClientName"] = currentClient.ClientName;
ViewData["LogoUri"] = currentClient.LogoUri;
}
}
ViewData["ReturnUrl"] = returnUrl;
return View();
}
I have a web application that uses Azure ACS and Azure AD to handle our authentication.
We have a user management feature in the web application that allows a user to create new users. This takes the details such as username, password, email etc. and uses the graph service to create a user in azure.
var newUser = new Microsoft.WindowsAzure.ActiveDirectory.User
{
userPrincipalName = user.UserName,
mailNickname = user.MailNickname,
accountEnabled = true,
displayName = user.FirstName + " " + user.Surname,
givenName = user.FirstName,
surname = user.Surname
};
newUser.passwordProfile = new PasswordProfile
{
forceChangePasswordNextLogin = false,
password = user.Password
};
var graphService = GetGraphService(tenantName);
graphService.AddTousers(newUser);
graphService.SaveChanges();
We are then required to create a record in the web application database for this user. The record needs the object ID from azure. So we use the graphService to get the newly-created user details. This is where my problem lies. It doesn't find the user.
private string GetObjectIdFromAzure(string userName, string tenantName)
{
var graphService = GetGraphService(tenantName);
var users = graphService.users;
QueryOperationResponse<Microsoft.WindowsAzure.ActiveDirectory.User> response;
response = users.Execute() as QueryOperationResponse<Microsoft.WindowsAzure.ActiveDirectory.User>;
var user = response.FirstOrDefault(x => x.userPrincipalName == userName);
return user != null ? user.objectId : "";
}
My code was working without any issues for a few months and only today I am having issues. What frustrates me more it that I have another deployment of the same code where it works without any issues. Some differences between the two deployments are:
The deployments use different Access control namespaces in Azure
The deployments have separate applications in Azure AD
One is https, one is http
The users for both system are under the same Directory.
I have put in logging in both deployments to get the number of users returned by
users.Execute()
In both systems it reported 100 (they share the same users)
Any ideas of what would cause this to stop working? I didn't change any code relating to this recently, I haven't changed any configuration on Azure and I didn't change the web.config of the application
The problem was caused by the fact that I was filtering the users after retrieving them. The graph API was only returning a maximum of 100 users.
So the process was like so:
User created in Azure
Success message returned
Web App searches Azure for user to get Object ID
Graph Api only returns top 100 users. User was not in top 100 alphabetically so error thrown
The reason it was working on our second deployment was that I was prefixing the user name with demo_ (we use this site to demo new features before releasing). This meant that it was being returned in the top 100 users.
I changed the code as follows so it filters during the retrieval instead of after:
private Microsoft.WindowsAzure.ActiveDirectory.User GetUserFromAzure(string userName, string tenantName, out DirectoryDataService graphService)
{
graphService = GetGraphService(tenantName);
var users = (DataServiceQuery<Microsoft.WindowsAzure.ActiveDirectory.User>)graphService.users.Where(x => x.userPrincipalName == userName);
QueryOperationResponse<Microsoft.WindowsAzure.ActiveDirectory.User> response;
response = users.Execute() as QueryOperationResponse<Microsoft.WindowsAzure.ActiveDirectory.User>;
var user = response.FirstOrDefault();
return user;
}
I'm trying to create a user with the DNN 7 services framework. I've taken my working code from my custom registration module and modified to work within a DNN webapi function.
When I get to the UserController.CreateUser call in the code below I receive a
"\"There was an error generating the XML document.\""
exception. My user makes it into the aspnet_Users table and the DNN users table but does not make it into the DNN userportals table. Any ideas would be appreciated.
private void CreateUser()
{
//Update DisplayName to conform to Format
UpdateDisplayName();
User.Membership.Approved = PortalSettings.UserRegistration == (int)Globals.PortalRegistrationType.PublicRegistration;
var user = User;
CreateStatus = UserController.CreateUser(ref user);
I finally found the issue. I was not setting the portal ID for my new users and DNN was excepting out when it was adding them to a portal. All it took was User.PortalId = 0 before the CreateUser call.
I have found by trial and error that the minimum needed to create a viable DNN user is:
UserInfo uiNewUser = new UserInfo();
uiNewUser.Username = "<myUsername>";
uiNewUser.Displayname = "<myDisplayname>";
uiNewUser.Email = "<myUserEmail>";
UserMembership newMembership = new UserMembership(uiNewUser);
newMembership.Password = "<myUserPassword>";
uiNewUser.Membership = newMembership;
uiNewUser.PortalID = <myPortalID>;
DotNetNuke.Security.Membership.UserCreateStatus uStatus;
uStatus = DotNetNuke.Security.Membership.MembershipProvider.Instance().CreateUser(ref uiNewUser);
RoleInfo newRole = RoleController.Instance.GetRoleByName(uiNewUser.PortalID, "Registered Users");
RoleController.Instance.AddUserRole(uiNewUser.PortalID, uiNewUser.UserID, newRole.RoleID, (RoleStatus)1, false, DateTime.MinValue, DateTime.MaxValue);
If any of these are missed out, parts of the user are created in the database, but the user may not be visible in the Admin list of users, or an Exception may be generated. Other details can be added later.
I am building a REST API for a DotNetNuke 6 website, making use of DNN's MVC-based Services Framework. However, I don't have any background in authentication, so I'm not even sure where to start.
Basically, we want our clients to be able to make GET requests for their portal's data, and we want some clients (but not all) to be able to POST simple updates to their user data.
I've been trying to search for information, but the trouble is I'm not sure what I'm searching for. DNN has different logins and roles, but I'm not sure if or how they factor in. I've heard of things like oAuth but my understanding of it is at the most basic level. I don't know if it's what I need or not and if or how it applies to DNN. Can anyone point me in the right direction?
UPDATE:
Based on the answer below about tying it with a module and further research, here is what I have done:
I created a module just for this service, and I added two special permissions for it: "APIGET" and "APIPOST." I assigned these to some test roles/test accounts in DNN. I wrote a custom authorize attribute that, given the module ID, checks if the current user has the necessary permission (either through roles or directly). As far as I can tell, tab ID is irrelevant in my case.
It appears to be working both with a web browser (based on the DNN account I'm logged into) and with a php script that sends an HTTP request with an account username/password.
The authorize attribute:
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Portals;
using DotNetNuke.Security;
using DotNetNuke.Security.Permissions;
using System.Web;
public class MyAuthorize : DotNetNuke.Web.Services.AuthorizeAttributeBase
{
public const string AuthModuleFriendlyName = "MyAuthModule";
public const string GETPermission = "APIGET";
public const string POSTPermission = "APIPOST";
public string Permission { get; set; }
protected override bool AuthorizeCore(HttpContextBase context)
{
ModuleController mc = new ModuleController();
ModuleInfo mi = mc.GetModuleByDefinition(PortalController.GetCurrentPortalSettings().PortalId, AuthModuleFriendlyName);
ModulePermissionCollection permCollection = mi.ModulePermissions;
return ModulePermissionController.HasModulePermission(permCollection, Permission);
}
}
The controller:
("mytest" is the endpoint for both GET and POST)
public class MyController : DnnController
{
[ActionName("mytest")]
[AcceptVerbs(HttpVerbs.Get)]
[DnnAuthorize(AllowAnonymous = true)]
[MyAuthorize(Permission = MyAuthorize.GETPermission)]
public string myget(string id = "")
{
return "You have my permission to GET";
}
[ActionName("mytest")]
[AcceptVerbs(HttpVerbs.Post)]
[DnnAuthorize(AllowAnonymous = true)]
[MyAuthorize(Permission = MyAuthorize.POSTPermission)]
public string mypost(string id = "")
{
return "You have my permission to POST";
}
}
The main way that you tie a service in the DNN Services Framework into DNN permissions is to associate the permissions with a module instance. That is, you'll require users of your service to identify which module they're calling from/about (by sending ModuleId and TabId in the request [headers, query-string, cookies, form]), then you can indicate what permissions they need on that module to take a particular action on the service.
You can use the SupportedModules attribute on your service, and pass in a comma-delimited list of module names, to ensure that only your own modules are being allowed. Then, add the DnnModuleAuthorize attribute at the service or individual action level to say what permission the user needs on that module. In your instance, you can also add the AllowAnonymous attribute on the GET actions, and have one DnnModuleAuthorize on the service, for the POST methods (and anything else). Note that you cannot put the AllowAnonymous attribute on the controller; it will override authorizations put at the action, making it impossible to make actions more restrictive.
You'll also want to add the ValidateAntiForgeryToken attribute on the POST actions, to protect against CSRF attacks.
If you don't have a module that naturally associates its permissions with your service, you can create one just for that purpose, solely to expose itself as a permissions management utility.
Once you've figured out the authorization piece above, DNN will take care of authentication using your forms cookie (i.e. AJAX scenarios are taken care of automatically), or via basic or digest authentication (for non-AJAX scenarios). That said, if you're doing non-AJAX, you'll need to figure out a way to validate the anti-forgery token only when it applies.
The Services Framework in DNN is what you are after. It allows you to provide a REST API that plugs directly into DNN security.
Here are some articles to help you get started:
http://www.dotnetnuke.com/Resources/Wiki/Page/Services-Framework-WebAPI.aspx
http://www.dotnetnuke.com/Resources/Blogs/EntryId/3327/Getting-Started-with-DotNetNuke-Services-Framework.aspx
Note, there are some difference in DNN 6 and DNN 7 when using the Services Framework:
http://www.dotnetnuke.com/Resources/Blogs/EntryId/3514/Converting-Services-Framework-MVC-to-WebAPI.aspx
Just wanted to note that the DnnModuleAuthorize attribute takes a PermissionKey parameter for custom permissions so you can do stuff like this:
[DnnModuleAuthorize(PermissionKey = "DELETEDATA")]
[HttpPost]
public HttpResponseMessage DeleteData(FormDataCollection data)
It doesn't look like you can supply your own error message with this so you might to wrap your method body like this instead and leave off the custom permission attribute:
[DnnModuleAuthorize(AccessLevel = SecurityAccessLevel.View)]
[HttpPost]
public HttpResponseMessage DeleteData(FormDataCollection data)
{
var errorMessage = "Could not delete data";
if (ModulePermissionController.HasModulePermission(ActiveModule.ModulePermissions,"DELETEDATA"))
{
// do stuff here
}
else
{
errorMessage = "User does not have delete permission";
}
var error = new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content =
new StringContent(
errorMessage)
};
return error;
}
Just wanted to add to #Richards comment for using the [DnnModuleAuthorize(PermissionKey = "DELETEDATA")] for custom permissions.
The full attribute should be:
[DnnModuleAuthorize(PermissionKey = "DELETEDATA", AccessLevel = SecurityAccessLevel.Edit)]
Leaving it blank does nothing as shown here: https://github.com/dnnsoftware/Dnn.Platform/blob/f4a5924c7cc8226cfe79bbc92357ec1a32165ada/DNN%20Platform/Library/Security/Permissions/PermissionProvider.cs#L810
I guess you require a plugin that allows you to construct GET and POST APIs. you can use this plugin I found on the DNN store. https://store.dnnsoftware.com/dnn-rest-api-custom-api-authentication-authorization.