I need to check if an user exists in AD and if so, retrieve some user information. I have been able to do this as shown below. But, it is very slow. Is there any way to do this faster?
Thanks!
using System;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
Console.WriteLine("Enter AD account name...");
string strADLoginName = Console.ReadLine();
using(PrincipalContext context = new PrincipalContext(ContextType.Domain,"DEVMC"))
{
using (UserPrincipal user = UserPrincipal.FindByIdentity(context, strADLoginName))
{
bool userExists = (user != null);
if (userExists)
{
Console.WriteLine("User exists");
Console.WriteLine(user.EmailAddress);
}
else
{
Console.WriteLine("User doesn't exist");
}
}
}
Console.ReadKey();
}
}
}
Well, the only real approach you could tak to make this faster would be to have the "PrincipalContext" be constructed once somewhere and cached for future use, so you don't have to re-create that context over and over again, every time you call that function.
Other than that - no, I don't see much room for improvement right here and now. What kind of app is this?? ASP.NET web apps, or Winforms, WPF, Silverlight??
Related
I am currently making a a leaderboard feature for my Mac OS X Unity game. I first tried Playfab but I kept getting an error saying "PlayFabException: Must be logged in to call this method PlayFab". I can't find a way to resolve this.
I have 2 scripts that does this, this is the code for the PlayFabManger script:
`using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using PlayFab;
using PlayFab.ClientModels;
using System;
public class PlayFabManager : MonoBehaviour
//public static PlayFabManager instance;
// Start is called before the first frame update
void Start()
{
//instance = this;
if (string.IsNullOrEmpty(PlayFabSettings.staticSettings.TitleId))
{
/*
Please change the titleId below to your own titleId from PlayFab Game Manager.
If you have already set the value in the Editor Extensions, this can be skipped.
*/
PlayFabSettings.staticSettings.TitleId = "F9F3D";
}
Login();
}
// Update is called once per frame
void Update()
{
}
void Login()
{
var request = new LoginWithCustomIDRequest
{
CustomId = SystemInfo.deviceUniqueIdentifier,
CreateAccount = true
};
PlayFabClientAPI.LoginWithCustomID(request, OnSuccess, OnError);
}
//private void OnLoginSuccess(LoginResult result)
//{
// //>> Call Client API here <<
// var getStoreItemsRequest = new GetStoreItemsRequest { StoreId = "[YourStoreId]" };// Please change this value to your own storeId from PlayFab Game Manager
// PlayFabClientAPI.GetStoreItems(getStoreItemsRequest, OnGetSuccess, OnError);
//}
void OnSuccess(LoginResult result)
{
print("Successful login create");
}
public void SendLeaderBoard(int score)
{
var request = new UpdatePlayerStatisticsRequest
{
Statistics = new List<StatisticUpdate>
{
new StatisticUpdate
{
StatisticName = "PlatformScore",
Value = score
}
}
};
PlayFabClientAPI.UpdatePlayerStatistics(request, OnLeaderboardUpdate, OnError);
}
void OnLeaderboardUpdate(UpdatePlayerStatisticsResult result)
{
print("Successful leaderboard sent");
}
void OnError(PlayFabError error)
{
print("Error while logging in/creating account!");
print(error.GenerateErrorReport());
}
public void GetLeaderBoard()
{
var request = new GetLeaderboardRequest
{
StatisticName = "PlatformScore",
StartPosition = 0,
MaxResultsCount = 10
};
PlayFabClientAPI.GetLeaderboard(request, OnLeaderboardGet, OnError);
}
private void OnLeaderboardGet(GetLeaderboardResult result)
{
foreach (var item in result.Leaderboard)
{
print(item.Position + " " + item.PlayFabId + " " + item.StatValue);
}
}
}
`
I also have a line of code in another script that is called at the start method and refers to the above script, where I pass in a Playerprefs.GetInt variable:
playFabManager.SendLeaderBoard(PlayerPrefs.GetInt("TtlPoints"));
Does anyone have any idea on resolving this error? Is there an easier way to achieve this leaderboard feature on Mac OS X using other extensions such as firebase or pubnub?
Sorry for my English, looking forward to hearing from you.
PubNub awesome, Beamable uses them for fabs leaderboards for Unity! Check them out.
I'll take the Firebase answer.
If you go the Firebase route, there is not an out of the box Leaderboard solution. There is an example open source repository that you can use to implement leaderboards on Realtime Database that should be relatively simple to implement.
Your second problem is that although Realtime Database does work on desktop (and the leaderboard in particular hasn't given me any issues), it is currently a beta feature only intended for use during development. If you file a related bug, the team will work to fix it, but it will probably be prioritized behind any mobile-features. You could implement it all using the REST API directly, but at this point the official Unity samples and documentation won't apply.
I'm using firebase anonymous authantication for my unity project.
As i always did when project is started i'm sending request to firebase for authantication,
but on my last project (which uses firebase sdk 6.16.0) my request creates new user everytime.
Here is some code about how i'm sending my request
Firebase.Auth.FirebaseAuth auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
auth.SignInAnonymouslyAsync().ContinueWith((task =>
{
if (task.IsCanceled)
{
Debug.Log("task cancelled");
return;
}
if (task.IsFaulted)
{
Debug.Log("task cancelled");
return;
}
if (task.IsCompleted)
{
Firebase.Auth.FirebaseUser userr = task.Result;
firebaseUserId = userr.UserId;
Debug.Log("firebaseUserId");
Debug.Log(firebaseUserId);
//every opening returns new uniq id here.
}
}));
On firebase authantication panel i only activated anonymous login. any suggestions?
Or is there any way to downgrade unity firebase version? i've tried to import old version which i was using on my last game (sdk 6.15.2) but there is some errors on resolver.
Basically, every time you call SignInAnonymouslyAsync you'll create a new user and the last one will be basically lost (it's more or less a random hash - anonymous as it's name suggests).
I'll typically do something like:
using System;
using Firebase.Auth;
using UnityEngine;
using UnityEngine.Events;
public class Login : MonoBehaviour
{
public UnityEvent OnSignInFailed = new UnityEvent();
public UserSignedInEvent OnUserSignedIn = new UserSignedInEvent();
public async void TriggerLogin()
{
var auth = FirebaseAuth.DefaultInstance;
var user = auth.CurrentUser;
if (user == null)
{
try
{
user = await auth.SignInAnonymouslyAsync();
}
catch (Exception e)
{
Debug.LogException(e);
OnSignInFailed.Invoke();
return;
}
}
// user definitely should not be null!
if (user == null)
{
OnSignInFailed.Invoke();
Debug.LogWarning("User still null!?");
return;
}
var userName = user.UserId;
OnUserSignedIn.Invoke(userName);
Debug.Log($"Logged in as {userName}");
}
[Serializable]
public class UserSignedInEvent : UnityEvent<string>
{
}
}
Note that for this code snippet, TriggerLogin is a public method so I can chain it off of a UnityEvent in the Unity editor.
Try and Put it some kind of check to find if used is already logged in. If yes, then do a silent login, if no then use anonymous login.
Currently you are straightaway logging in user even if they logged in last time they opened the Application.
Try this link: https://github.com/firebase/quickstart-unity/issues/266#issuecomment-447981995
I'm porting a website to dnx core/aspnet5/mvc6. I need to store passwords to 3rd party sites in the database (it's essentially an aggregator).
In earlier versions of mvc, I did this using classes like RijndaelManaged. But those don't appear to exist in dnx core. In fact, I haven't been able to find much documentation on any general purpose encryption/decryption stuff in dnx core.
What's the recommended approach for encrypting/decrypting single field values in an mvc6 site? I don't want to encrypt the entire sql server database.
Or should I be looking at a different approach for storing the credentials necessary to access a password-protected 3rd party site?
See the DataProtection API documentation
Their guidance on using it for persistent data protection is a little hedgy but they say there is no technical reason you can't do it. Basically to store protected data persistently you need to be willing to allow unprotecting it with expired keys since the keys could expire after you protect it.
To me it seems reasonable to use it and I am using it in my own project.
Since the IPersistedDataProtector only provides methods with byte arrays I made a couple of extension methods to convert the bytes back and forth from string.
public static class DataProtectionExtensions
{
public static string PersistentUnprotect(
this IPersistedDataProtector dp,
string protectedData,
out bool requiresMigration,
out bool wasRevoked)
{
bool ignoreRevocation = true;
byte[] protectedBytes = Convert.FromBase64String(protectedData);
byte[] unprotectedBytes = dp.DangerousUnprotect(protectedBytes, ignoreRevocation, out requiresMigration, out wasRevoked);
return Encoding.UTF8.GetString(unprotectedBytes);
}
public static string PersistentProtect(
this IPersistedDataProtector dp,
string clearText)
{
byte[] clearBytes = Encoding.UTF8.GetBytes(clearText);
byte[] protectedBytes = dp.Protect(clearBytes);
string result = Convert.ToBase64String(protectedBytes);
return result;
}
}
I also created a helper class specifically for protecting certain properties on my SiteSettings object before it gets persisted to the db.
using cloudscribe.Core.Models;
using Microsoft.AspNet.DataProtection;
using Microsoft.Extensions.Logging;
using System;
namespace cloudscribe.Core.Web.Components
{
public class SiteDataProtector
{
public SiteDataProtector(
IDataProtectionProvider dataProtectionProvider,
ILogger<SiteDataProtector> logger)
{
rawProtector = dataProtectionProvider.CreateProtector("cloudscribe.Core.Models.SiteSettings");
log = logger;
}
private ILogger log;
private IDataProtector rawProtector = null;
private IPersistedDataProtector dataProtector
{
get { return rawProtector as IPersistedDataProtector; }
}
public void Protect(ISiteSettings site)
{
if (site == null) { throw new ArgumentNullException("you must pass in an implementation of ISiteSettings"); }
if (site.IsDataProtected) { return; }
if (dataProtector == null) { return; }
if (site.FacebookAppSecret.Length > 0)
{
try
{
site.FacebookAppSecret = dataProtector.PersistentProtect(site.FacebookAppSecret);
}
catch (System.Security.Cryptography.CryptographicException ex)
{
log.LogError("data protection error", ex);
}
}
// ....
site.IsDataProtected = true;
}
public void UnProtect(ISiteSettings site)
{
bool requiresMigration = false;
bool wasRevoked = false;
if (site == null) { throw new ArgumentNullException("you must pass in an implementation of ISiteSettings"); }
if (!site.IsDataProtected) { return; }
if (site.FacebookAppSecret.Length > 0)
{
try
{
site.FacebookAppSecret = dataProtector.PersistentUnprotect(site.FacebookAppSecret, out requiresMigration, out wasRevoked);
}
catch (System.Security.Cryptography.CryptographicException ex)
{
log.LogError("data protection error", ex);
}
catch (FormatException ex)
{
log.LogError("data protection error", ex);
}
}
site.IsDataProtected = false;
if (requiresMigration || wasRevoked)
{
log.LogWarning("DataProtection key wasRevoked or requires migration, save site settings for " + site.SiteName + " to protect with a new key");
}
}
}
}
If the app will need to migrate to other machines after data has been protected then you also want to take control of the key location, the default would put the keys on the OS keyring of the machine as I understand it so a lot like machinekey in the past where you would override it in web.config to be portable.
Of course protecting the keys is on you at this point. I have code like this in the startup of my project
//If you change the key persistence location, the system will no longer automatically encrypt keys
// at rest since it doesn’t know whether DPAPI is an appropriate encryption mechanism.
services.ConfigureDataProtection(configure =>
{
string pathToCryptoKeys = appBasePath + Path.DirectorySeparatorChar
+ "dp_keys" + Path.DirectorySeparatorChar;
// these keys are not encrypted at rest
// since we have specified a non default location
// that also makes the key portable so they will still work if we migrate to
// a new machine (will they work on different OS? I think so)
// this is a similar server migration issue as the old machinekey
// where we specified a machinekey in web.config so it would not change if we
// migrate to a new server
configure.PersistKeysToFileSystem(new DirectoryInfo(pathToCryptoKeys));
});
So my keys are stored in appRoot/dp_keys in this example.
If you want to do things manually;
Add a reference to System.Security.Cryptography.Algorithms
Then you can create instances of each algorithm type via the create method. For example;
var aes = System.Security.Cryptography.Aes.Create();
I've been trying to understand how the reset password & account confirmation works in ASP.NET Identity. I'd just like to know if the Tokens are being stored and if so, where?
The links I receive when I'm using the password reset feature look something like this
http://localhost:1470/Account/ResetPassword?userId=a8b1389c-df93-4dfc-b463-541507c1a4bc&code=yhUegXIM9SZBpPVbBtv22kg7NO7F96B8MJi9MryAadUY5XYjz8srVkS5UL8Lx%2BLPYTU6a6jhqOrzMUkkMyPbEHPY3Ul6%2B%2F0s0qQvtM%2FLLII3s29FgkcK0OnjX46Bmj9JlFCUx53rOH%2FXMacwnKDzoJ1rbrUyypZiJXloIE50Q6iPuMTUHbX9O%2B3JMZtCVXjhhsHLkTOn9IVoN6uVAOMWNQ%3D%3D
My guess is that the tokens are stored in the link itself since I cannot find any trace of it anywhere else. Maybe someone knows for sure?
As I mentioned in the comment
"Tokens are generated using the SecurityStamp and validating against the SecurityStamp and not storing anywhere in database or local file storage. If you update the SecurityStamp, then previous tokens are no longer valid."
#DSR is correct but I would like to add some information to this as well.
If you have set up a Web project with Individual User Accounts go to:
App_Start -> IdentityConfig.cs
There you will see code like this:
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
The description for DataProtectorTokenProvider<TUser, TKey> gives the information:
Represents a token provider that uses an IDataProtector to generate
encrypted tokens based off of the security stamp.
https://learn.microsoft.com/en-us/previous-versions/aspnet/dn613280(v%3dvs.108)
We can however try to dig a bit deeper how it really works. The token verification will fail if different Application Pool Identities are used for creating and validating a token on a single server. This points to that the actual protection mechanism would look something like this:
System.Security.Cryptography.ProtectedData.Protect(userData, entropy, DataProtectionScope.CurrentUser);
Given that it works if all sites use the same Application Pool Identity points to this as well. Could also be DataProtectionProvider with protectionDescriptor "LOCAL=user". It should have worked with different Application Pool Identities if LOCAL=machine was set.
new DataProtectionProvider("LOCAL=user")
https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.dataprotector?view=netframework-4.7.2
https://learn.microsoft.com/en-us/uwp/api/windows.security.cryptography.dataprotection.dataprotectionprovider
dataProtectionProvider is of type IDataProtectionProvider.
It is injected in Startup.Auth.cs like this:
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
CreatePerOwinContext is located in the assembly Microsoft.AspNet.Identity.Owin -> AppBuilderExtensions.cs. Both ASP.NET Identity and ASP.NET Core Identity are open source and can be viewed at GitHub.
public static IAppBuilder CreatePerOwinContext<T>(this IAppBuilder app,
Func<IdentityFactoryOptions<T>, IOwinContext, T> createCallback,
Action<IdentityFactoryOptions<T>, T> disposeCallback) where T : class, IDisposable
{
if (app == null)
{
throw new ArgumentNullException("app");
}
if (createCallback == null)
{
throw new ArgumentNullException("createCallback");
}
if (disposeCallback == null)
{
throw new ArgumentNullException("disposeCallback");
}
app.Use(typeof (IdentityFactoryMiddleware<T, IdentityFactoryOptions<T>>),
new IdentityFactoryOptions<T>
{
DataProtectionProvider = app.GetDataProtectionProvider(),
Provider = new IdentityFactoryProvider<T>
{
OnCreate = createCallback,
OnDispose = disposeCallback
}
});
return app;
}
https://github.com/aspnet/AspNetIdentity/blob/master/src/Microsoft.AspNet.Identity.Owin/Extensions/AppBuilderExtensions.cs
https://archive.codeplex.com/?p=aspnetidentity#src/Microsoft.AspNet.Identity.Owin/Extensions/AppBuilderExtensions.cs
app.GetDataProtectionProvider() is in turn located in assembly Microsoft.Owin.Security that is also Open Source.
public static IDataProtectionProvider GetDataProtectionProvider(this IAppBuilder app)
{
if (app == null)
{
throw new ArgumentNullException("app");
}
object value;
if (app.Properties.TryGetValue("security.DataProtectionProvider", out value))
{
var del = value as DataProtectionProviderDelegate;
if (del != null)
{
return new CallDataProtectionProvider(del);
}
}
return null;
}
https://github.com/aspnet/AspNetKatana/blob/release/src/Microsoft.Owin.Security/DataProtection/AppBuilderExtensions.cs
We can also see that CreateDataProtector has a fallback to the implementation DpapiDataProtectionProvider.
private static IDataProtectionProvider FallbackDataProtectionProvider(IAppBuilder app)
{
return new DpapiDataProtectionProvider(GetAppName(app));
}
When reading about DpapiDataProtectionProvider(DPAPI stands for Data Protection Application Programming Interface) the description says:
Used to provide the data protection services that are derived from the
Data Protection API. It is the best choice of data protection when you
application is not hosted by ASP.NET and all processes are running as
the same domain identity.
The Create method purposes are described as:
Additional entropy used to ensure protected data may only be
unprotected for the correct purposes.
The protector class itself then looks like this:
using System.Security.Cryptography;
namespace Microsoft.Owin.Security.DataProtection
{
internal class DpapiDataProtector : IDataProtector
{
private readonly System.Security.Cryptography.DpapiDataProtector _protector;
public DpapiDataProtector(string appName, string[] purposes)
{
_protector = new System.Security.Cryptography.DpapiDataProtector(appName, "Microsoft.Owin.Security.IDataProtector", purposes)
{
Scope = DataProtectionScope.CurrentUser
};
}
public byte[] Protect(byte[] userData)
{
return _protector.Protect(userData);
}
public byte[] Unprotect(byte[] protectedData)
{
return _protector.Unprotect(protectedData);
}
}
}
https://learn.microsoft.com/en-us/previous-versions/aspnet/dn253784(v%3dvs.113)
Im working on a example that im trying to use a webservice make it in .net c# and i have a some questions. I have a method in webservice like that:
public string login(string user, string pass)
{
//string msg = "";
string res = "";
person n = new person(user, pass);
if (n.login())
{
Session["user"] = Server.HtmlEncode(u);
setTimeOutLogIn(u);
res = u;
}
else
{
// msg = "Error";
}
return res;
}
now with this I return a string with a unique user for flex to make a state of user.
my doubt is how can I work properly on flex with session?
Other question and problem having here, and is a big one:
when is made any request to webservice the flex only answer the second ask. for example:
public function LogUser()
{
var name:String=Login.text;
var pass:String=Password.text;
Service.login.send(name, pass);
checkLogin();
}
public function checkLogin():Boolean
{
var boll:Boolean= new Boolean;
Service.checkLogin.send(util);
boll = Service.checkLogin.lastResult;
if(boll==false)
{
Llogout.visible=false;
Lregist.visible=true;
Llogin.visible=true;
Luser.visible=false;
currentState="default";
}
else
{
Llogin.visible=false;
Llogout.visible=true;
Lregist.visible=false;
Luser.visible=true;
Luser.text=util;
currentState="default";
}
return boll;
}
<s:operation name="login"> </s:operation>
<s:operation name="checkLogin" result="checkLog()"></s:operation>
</s:WebService>
this simple operation only respond rightly for the second time.
Any thoughts?
Sorry for the trouble
Webservice calls are not like website calls. You will not be able to set a user session that will persist and only be available to your users session. You may want to check out FlorineFX I dont think it will do exactly what you want but I know you can do some of this stuff and interact with the asp.net more like a website. We used this for several projects a couple years ago.