To what degree is PasswordVault securing and isolating data? - c#

I am considering using PasswordVault to store a sensitive piece of data in my Windows Store app.
I have already done some basic research around examining the protection this class provides. I wrote two sample applications, the first writes a bit of data to the vault and the second tries to get that data.
It appears that even though the second application is using the same key as the first app used in saving the data; the second app cannot retrieve that data. This is good.
Does anybody know how the PasswordVault isolates the data to one App? For another app to get it's hands on my app's PasswordVault data would it have to impersonate my App's sid?
For clarity:
App1 does this
const string VAULT_RESOURCE = "App1 Credentials";
var vault = new PasswordVault();
vault.Add(new PasswordCredential(VAULT_RESOURCE, "Foo", "Bar"));
App2 does this
var vault = new PasswordVault();
const string VAULT_RESOURCE = "App1 Credentials";
try
{
var creds = vault.FindAllByResource(VAULT_RESOURCE).FirstOrDefault();
if (creds != null)
{
UserName = creds.UserName;
Password.Text = vault.Retrieve(VAULT_RESOURCE, "Foo").Password;
}
}
catch (COMException)
{
// this exception likely means that no credentials have been stored
}
Now App2 receives an exception indicating no such credential exists. This is good. What I want to understand is to what degree would App2 need to go to get it's hands on the data App1 stored.

Related

Azure functions and persist token cache file

I have an HTTP triggered function (.NET 3.1 TLS, running not from zip package), that connects to my personal OneDrive and dropping files.
To minimize authentication prompts I used this approach to serialize token cache: https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-net-token-cache-serialization?tabs=custom#simple-token-cache-serialization-msal-only
On localhost it works great, but it is not so good while running function on Azure - the cache file is lost quite often.
I put in on Path.GetTemporaryPath(). Not sure which location is the best for such purpose. However the cache seems to be bound to a computer that created the file: when I use cache file, created on my localhost and uploaded to Azure, then using of such file shows errors around getting account details / enumeration.
Any ideas how to get this fixed by minimal cost? My app is using only one token: for my, personal, OneDrive.
The final solution is:
remove ProtectedData from code from the sample custom token serialization helper, because it encrypts the file with current profile or machine
save args.TokenCache.DeserializeMsalV to Azure Storage Blob and read it later.
So I've made changes in code from https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-net-token-cache-serialization?tabs=custom#simple-token-cache-serialization-msal-only to the following:
EnableSerialization:
string cstring = System.Environment.GetEnvironmentVariable("AzureWebJobsStorage");
string containerName = System.Environment.GetEnvironmentVariable("TokenCacheStorageContainer");
try { bcc = new BlobContainerClient(cstring, containerName); } catch { }
if (!bcc.Exists())
{
bcc = (new BlobServiceClient(cstring)).CreateBlobContainerAsync(containerName).GetAwaiter().GetResult();
}
tokenCache.SetBeforeAccess(BeforeAccessNotification);
tokenCache.SetAfterAccess(AfterAccessNotification);
BeforeAccessNotification:
lock (FileLock)
{
var blob = bcc.GetBlobClient("msalcache.bin3");
if (blob.Exists())
{
var stream = new MemoryStream();
blob.DownloadToAsync(stream).GetAwaiter().GetResult();
args.TokenCache.DeserializeMsalV3(stream.ToArray());
}
}
AfterAccessNotification:
if (args.HasStateChanged)
{
lock (FileLock)
{
// reflect changesgs in the persistent store
(bcc.GetBlobClient("msalcache.bin3")).UploadAsync(new MemoryStream(args.TokenCache.SerializeMsalV3()),true).GetAwaiter().GetResult();
}
}

Add 2fa authenticator to user

I have been trying to work out how to enable 2f login with Google Authentication in my Identity server 4 application.
2fa works fine with both email and phone.
if i check
var userFactors = await _userManager.GetValidTwoFactorProvidersAsync(user);
it has two email and phone. I am assuming that this would be the two factor providers that have been set up for this user.
Now if i check _usermanager again there is a field called tokenproviders. Which appears to contain default, email, phone, and authenticator. I assume these are the ones that Asp .net identity is configured to deal with.
I have worked out how to create the secret needed to genreate the QR code for the authecator app. As well has how to build the QR code and to test the code
var code = _userManager.GenerateNewAuthenticatorKey();
var qr = AuthencatorHelper.GetQrCodeGoogleUrl("bob", code, "My Company");
var user = await _signInManager.TwoFactorAuthenticatorSignInAsync(codeFromAppToTestWith, true, false);
if (user == null)
{
return View("Error");
}
Now the problem. I have gone though every method I can find on the user trying to work out how to add another token provider to the user.
How do I assign a new token provider to the user and supply the secret code needed to create the authentication codes?? I am not even seeing any tables in the database setup to handle this information. email and phone number are there and there is a column for 2faenabled. But nothing about authenticator.
I am currently looking into creating a custom usermanager and adding a field onto the application user. I was really hoping someone had a better idea.
From what I can see, you are generating a new authenticator key each time the user needs to configure an authenticator app:
var code = _userManager.GenerateNewAuthenticatorKey();
You should be aware that using GenerateNewAuthenticatorCodeAsync will not persist the key, and thus will not be useful for 2FA.
Instead, you need to generate and persist the key in the underlying storage, if it not already created:
var key = await _userManager.GetAuthenticatorKeyAsync(user); // get the key
if (string.IsNullOrEmpty(key))
{
// if no key exists, generate one and persist it
await _userManager.ResetAuthenticatorKeyAsync(user);
// get the key we just created
key = await _userManager.GetAuthenticatorKeyAsync(user);
}
Which will generate the key if not already done and persist it in the database (or any storage configured for Identity).
Without persisting the key inside the storage, the AuthenticatorTokenProvider will never be able to generate tokens, and will not be available when calling GetValidTwoFactorProvidersAsync.

Publishing tweets from C# Windows service using Tweetinvi or similar

I am looking into publishing some service status updates on Twitter using Tweetinvi, which seems like a good library for doing that sort of thing, but I am just starting out looking into this so using it is not set in stone.
However, one thing my research has not yielded yet, is an obvious way to handle Twitter authentication in what is essentially a headless service. I have created an app with Twitter, so I have my consumer key and secret, and I can do the "app only" auth to request user info, get their followers etc., but of course I have no right to publish tweets.
So my ambition is (once this is out of beta) to create a proper twitter account, somehow have the service authenticate towards that account, and then publish status updates from the general service at defined intervals. It is a fairly simple idea.
Of course, I can do something like the PIN based authentication mentioned here:
https://github.com/linvi/tweetinvi/wiki/Authentication
I can run that manually, get the PIN code, and proceed with the workflow. But will this require reauthentication at regular intervals, or will it basically be valid "forever"? I am looking for a way to make this as automatic as possible, and having to redo the auth every x hours is a huge dent in this dream, if not a showstopper.
Of course I will have the password for the twitter account used to publish statuses, but I don't see a way to do a good old fashioned login without manual user intervention - what options do I have?
This behavior is by design. Twitter uses OAuth, which is a protocol with the purpose of allowing a user to authorize an application. This is good for the user because otherwise, you or anyone else can perform actions on their behalf without them knowing.
With that in mind, the only way to do this is to have the user explicitly authorize your app. Here's an example of how to do this with LINQ to Twitter, which I wrote, using ASP.NET MVC. When the user visit's your page, you can have a button that re-directs them to the OAuthController below to the BeginAsync action.
using System;
using System.Configuration;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Mvc;
using LinqToTwitter;
namespace MvcDemo.Controllers
{
public class OAuthController : AsyncController
{
public ActionResult Index()
{
return View();
}
public async Task<ActionResult> BeginAsync()
{
//var auth = new MvcSignInAuthorizer
var auth = new MvcAuthorizer
{
CredentialStore = new SessionStateCredentialStore
{
ConsumerKey = ConfigurationManager.AppSettings["consumerKey"],
ConsumerSecret = ConfigurationManager.AppSettings["consumerSecret"]
}
};
string twitterCallbackUrl = Request.Url.ToString().Replace("Begin", "Complete");
return await auth.BeginAuthorizationAsync(new Uri(twitterCallbackUrl));
}
public async Task<ActionResult> CompleteAsync()
{
var auth = new MvcAuthorizer
{
CredentialStore = new SessionStateCredentialStore()
};
await auth.CompleteAuthorizeAsync(Request.Url);
// This is how you access credentials after authorization.
// The oauthToken and oauthTokenSecret do not expire.
// You can use the userID to associate the credentials with the user.
// You can save credentials any way you want - database,
// isolated storage, etc. - it's up to you.
// You can retrieve and load all 4 credentials on subsequent
// queries to avoid the need to re-authorize.
// When you've loaded all 4 credentials, LINQ to Twitter will let
// you make queries without re-authorizing.
//
//var credentials = auth.CredentialStore;
//string oauthToken = credentials.OAuthToken;
//string oauthTokenSecret = credentials.OAuthTokenSecret;
//string screenName = credentials.ScreenName;
//ulong userID = credentials.UserID;
//
return RedirectToAction("Index", "Home");
}
}
}
After the user authorizes your application, Twitter redirects them back to the CompleteAsync method. Notice the comments on how to extract values from the auth.CredentialStore. Save those in your DB and then retrieve them in your service to make calls on the user's behalf.
Those credentials don't change, but the user can possibly de-authorize your application at some time in the future - at which time you'll need to get them to authorize again. You can get the entire sample code at the LINQ to Twitter ASP.NET Samples page.

Updating cell in public spreadsheet without need for auth?

I have set a spreadsheet to public which I assume would mean a user shouldn't need authorization to access and make changes to it, I should only need to provide my client id and secret? (I'm the only person who will be using this app and the spreadsheet is on my own Google account which is also the owner of the app)
I went through the documentation here: https://developers.google.com/google-apps/spreadsheets/?hl=en
My code works perfectly - it basically just updates a single cell in a spreadsheet with a function and then returns the value of that cell.
The issue is, I don't want to have to keep authorizing through the webpage. Is it possible to skip the need to authorize? Or at least authorize through code automatically instead of manually doing it through a webpage?
using Google.GData.Client;
using Google.GData.Spreadsheets;
namespace Spreadsheet{
class Program{
static void Main(){
OAuth2Parameters parameters = new OAuth2Parameters();
parameters.ClientId = "client-id-here";
parameters.ClientSecret = "client-secret-here";
parameters.RedirectUri = "urn:ietf:wg:oauth:2.0:oob"; //I'm not even sure what this is, I assume it's only necessary for web based applications
parameters.Scope = "https://spreadsheets.google.com/feeds https://docs.google.com/feeds";
//This is where the user is required to navigate to a page and retrieve access code
string authorizationUrl = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);
parameters.AccessCode = Console.ReadLine();
OAuthUtil.GetAccessToken(parameters);
string accessToken = parameters.AccessToken;
GOAuth2RequestFactory requestFactory =
new GOAuth2RequestFactory(null, "Spreadsheet", parameters);
SpreadsheetsService service = new SpreadsheetsService("Spreadsheet");
service.RequestFactory = requestFactory;
//spreadsheet related code here..
}
}
}
Where is this script running? The code sample you are using tries to get a token every time you run it. You have two options
If this code runs on a server and it can store the refresh token securely then, manually get a refresh token and change the script to just get a new access token (using that refresh token) to do the update.
Change to using a service account. Service accounts are built to handle these kind of use cases. You get a service account and in the spreadsheet give access to service account (share with it) and using service account you make a request to get an access token that you can use.

How to get user name, email, etc. from MobileServiceUser?

After a lot of digging around I've got my WPF application signing users in via Azure Mobile Service. My Mobile Service is connected to an Azure Active Directory that I have set up. However, when I log the user in with MobileServiceClient.LoginAsync(...) the MobileServiceUser UserId is in an unreadable hash it seems. For example it looks like: "Aad:X3pvh6mmo2AgTyHdCA3Hwn6uBy91rXXXXXXXXXX". What exactly is this?
I'd like to grab the user's display name to use but I can't figure out how.
That is the userID of Azure Active Directory. You need to create a service to expose your AAD info through a service and retrieve the additional information using the access token you get from your user.
First:
ServiceUser user = this.User as ServiceUser;
var identities = await user.GetIdentitiesAsync();
var aad = identities.OfType<AzureActiveDirectoryCredentials>().FirstOrDefault();
var aadAccessToken = aad.AccessToken;
var aadObjectId = aad.ObjectId;
This will give you the access token and objectID , then you need to query the information through AAD graphy API.
https://msdn.microsoft.com/library/azure/dn151678.aspx
Look at the sample request part. You should provide the query with the access token you got and objectId.
Here is an alternative approach, after reading http://justazure.com/azure-active-directory-part-2-building-web-applications-azure-ad/ scroll to the section on Identity in .Net it talks how claims are a standard part of the framework. So once you get the credentials object like provided by #beast
var aad = identities.OfType<AzureActiveDirectoryCredentials>().FirstOrDefault();
You can actually grab a dictionary with the various properties. Examples of some the properties can be found at https://msdn.microsoft.com/en-us/library/system.identitymodel.claims.claimtypes(v=vs.110).aspx
So from there you can do the following:
if (aad != null)
{
var d = aad.Claims;
var email = d[ClaimTypes.Email];
}
I did this to pull the user id which was cross referenced in a table. FYI I am using App Service, but I believe the credentials object is the same in Mobile Service

Categories