Office Add-ins : Windows Authentication (Get User Name who Logged into Machine) - authentication

Friends,
I need some help on Word API Authentication.
Scenario:
Our articles has meta data which contains who can work on the articles (User1, User2), we need to know user_name (window's id) who logged into the machine so that we can authenticate the users against article metadata without asking them to log-in each time.
Workflow:
Article Creator Process is responsible for creating the document. This process will create word document and will be transferred to the user.
Article processor is adding custom xml part into document such as User Name, Document ID etc.
Authentication Rule is simple here. If article metadata contains your name then only you can work else not.
We need to match article meta data name with user who is opening the document. So here we need to know who log-ed into the machine.
How we can get this information for Online and Offline ?
We don't want our desktop users to enter the credentials again and again. For desktop which is (90% users will use desktop) is should be pretty straight forward, get user name and match it with article metadata.
Appreciate any help on this, any alternative solutions to handle this are most welcome.

There is no way to find out the current user's username. You can get the unique ID of the user in terms of a GUID-like entity, though, so I suppose you could store the user GUID into the custom XML part instead. The GUID corresponds to the Microsoft account or OrgID identity of the user.
See https://msdn.microsoft.com/en-us/library/office/jj164035.aspx for more info, particularly the "To load a test license from your Visual Studio project" section that describes the structure of the validation token.
Alternatively, if you can trust your users (i.e., it's just identification, not authentication), have them type in their name once, and then store it in the browser's localStorage.

Related

How to manage user updates and deletions in OIDC and SPA architecture

i am making a set of applications that share a common oidc provider (in my control), where the users will be created.
One of my applications is a stateless SPA "meeting" app where you can schedule meetings with other users, and you login purely by an OIDC token.
I am having a hard time thinking a strategy about the following
Should the "user" details be stored in the meeting app after a login? So let's say user A exists in the provider, then enters the meeting app. Should i save user A in the meeting app DB?
How to handle change of user details? Let's say user A changes name to User B in the provider. Until he logs in again, all the other users see him as User A still in the "contacts" list. What is the usual practice for solving this?
How to handle deletions in the provider. I need someway to signal that "deleted in provider -> deleted in app". Should i constantly poll the provider and get any missing users, create a push system, or is this just unneeded?
Thanks a lot in advance
That's actually a very good question and rarely explained well in online articles. Hopefully the below detailed notes help you with your solution. I have answered your questions at the end.
OAUTH USER DATA
Typically the core user data such as name, email etc belongs in the Authorization Server. It contains Personally Identifiable Information (PII) and changes are audited there. This is explored in further detail in the Privacy and GDPR article.
DOMAIN SPECIFIC USER DATA
This might include fields like a user's application preferences, and you may end up with data similar to this in your APIs:
Field
Description
id
A database surrogate key for the user
subject
The subject claim from an OAuth access token, which is typically a GUID or something similar
archived
A boolean flag set to true when a user is active in the app
field 1
A domain specific value
field 2
A domain specific value
To get OAuth user data within your applications your APIs can call the Authorization Server's SCIM 2.0 endpoint as described in this User Management article.
AUTHORIZATION AND ROLES
Interestingly, roles and application specific rights could be stored in either of the above data sources. You may want to start by putting roles in the OAuth data, but for cases where they are very domain specific and change often, I have found that storing them in my own API data works best.
DOMAIN SPECIFIC USER DATA AND ACCESS TOKENS
Sometimes you need to include domain specific user data (which might include roles) in access tokens. This Claims Article explains how claims can be looked up from external APIs during token issuance. This typically involves a REST call from the Authorization Server to one or more APIs, providing the subject value for which tokens will be issued.
CONSISTENT USER IDENTITY IN YOUR APPS
A user can potentially authenticate in multiple ways, such as default password / corporate login / social login. You may need to use some custom Account Linking logic to ensure that the subject field in the access token gets the same value in all cases. This prevents you ever creating duplicate users within your application.
USER INFO CHANGES
These are typically made by end users within an application screen, and your APIs then call SCIM endpoints to update the core OAuth data. A common case is when a user changes their name and / or email, eg if the user gets married. Note that the subject value remains the same after this edit.
USER ADMINISTRATION
In scenarios where corporate assets are used, an administrator typically provisions users, either individually or in bulk. This can be done via the SCIM endpoint. In some cases administrator actions may need to save data to both data sources - eg to create a user and set roles + application preferences.
USER INFO EVENTS
Sometimes your application needs to know about a user info event, such as new, deleted or changed users. This can be managed via Event Listeners, where an extension to the Authorization Server calls back your domain specific APIs when a user edit occurs. When a user is deleted in the OAuth user data you might then update the user's application state to archived.
DATA MIGRATIONS
Finally it is worth mentioning that the above also supports migrating to an OAuth architecture or between providers:
Get a combined view of the user data before migration
Insert all existing users into the new OAuth system via SCIM
Update the combined view of the user data with new subject values
Update your domain specific data with new subject values
SUMMARY
So to answer your questions:
Aim to avoid this because it adds complexity, though in some cases you may need to denormalise for performance reasons. The OAuth user data should remain the source of truth and the only place where edits occur to PII data.
Your meeting app would need to join on the OAuth user data and domain specific user data and present a list. This would probably involve caching a combined view of the user data.
See Administrator Events above. Your API should be informed of OAuth user data changes via an event, then your SPA would get current data on the next refresh.
When implemented like this you end up with simple code and a well defined architecture. Some providers may not provide all of these features though, in which case you may need an alternative approach to some areas.

Limited edit rights on pages in Piranha.Core

I've found piranha.core cms this week and it looks great and very extendable.
I need CMS in a site that will need user registration for a fundraiser event for a charity. This would be for donators as well as volunteers raising money.
But I also want some users to be able to create news post, etc.
This project would require volunteers to be able to edit content on a profile page and for dontators to track their donations.
I'd like the accounts of my registrants, volunteers and content creators to be the same accounts.
The Piranha.core example uses 'Piranha Identity With Seed', which in turn uses asp.net identity as I've seen in the UserController.
So here's what I'd like to do :
Register users,
Create a page for a volunteer when a volunteer registers,
Assign rights to the volunteer to be able to edit/publish only their own page.
So I think I could register a user using the Asp.net Identity UserManager, copy a template page using the PageEditService, but the question is: can I limit the rights of a user to just being able to edit the user's profile page? (maybe not even all content on the page)
Cheers,
Jurjen
The manager permissions are function based so that user groups can be assigned the rights to perform different actions on different types of entities. There is no support at the moment to limit access to specific pages to specific users.
My advice is to create the edit view in the front-end application as it is extremely easy to load & update pages with the existing Api, and this will probably give you more freedom in regards to what you want the users to be able to edit on the page.
For connecting the created pages with their users you could either:
Add a StringField to the PageType containing the user id, or
Add you own database table in your own DbContext connecting the user & page.
I would also consider using Posts for your volunteers instead of Pages. This way you could use the built in functionality for creating a Volunteer archive where volunteers could be categorized and tagged for easier searching. It will also make sure the sitemap stays uncluttered and focused.
Best regards

External Login Account vs. Native Login Account

I am brand new to Visual Studio 2012 and MVC 4, and I've been working with the SimpleMembershipProvider via the WebMatrix.WebData library.
I'd like to integrate Facebook as an external login source down the road, but it's not a requirement as of right now. However, to get a decent feel for what it would take, I've been following the tutorial and guide found here - http://www.asp.net/mvc/tutorials/mvc-4/using-oauth-providers-with-mvc.
My question :
If a user has already been created using :
WebSecurity.CreateUserAndAccount(model.Email, model.Password);
WebSecurity.Login(model.Email, model.Password);
Can they be "upgraded" to an oAuthMemebership account in the future, if they choose to use their Facebook credentials instead of the email and password they created when first signing up?
I couldn't find a clear answer to this question in the guide, or elsewhere, so I'm hoping someone can clarify how that process may work.
The SimpleMembership setup allows for a local and multiple OAuth logins all sharing the same UserProfile - so a single user can login with either a local password, or FacebOogLiveWitter.
(I should state, that I'm assuming in this answer that the OAuth provider does not send back a matching piece of information for a local account. If they do then the principles of actually performing the merge are the same, but the complexity and steps are vastly reduced.)
The OAuth registration process will refuse the user if they use an existing user name, rather than try and merge two accounts. Therefore this isn't simple, you'll have to build the functionality yourself. The process is complex as there are many directions the user can approach this from (so you could simplify by only supporting one or two), and you need to enforce security as well in case someone tries to merge into an account they don't own.
I will assume you are comfortable with the link you've posted, and you've followed the Facebook help at (for example) Facebook Login and The Login Flow for Web (without JavaScript SDK) so you have a working test application.
Your general process has to have multiple user journey approaches to make sense to a user:
for a logged in user (with a local account)
let them login to facebook and associate the accounts
let them merge an existing account on your site which uses a facebook login
for a logged-in user (with a facebook account)
let them create a local account
let them merge an existing local account on your site
for a non logged in user who tries to register a local account
let them merge this new account with a facebook login that is already registered, and do that as part of the registration process
for a non logged in user who tries to register (or log in for the first time with) a facebook account
let them link this with an existing local account as part of the registration process
etc.
ASK PERMISSION
(You can skip this if the OAuth provider has sent back a matching identifying piece of information, such as an email address).
You should enforce confirmation security, usually through email confirmation sent to the target account of the merge. Otherwise:
someone can login to your site with facebook for the first time
during that process say they "own" the email address or username of a local account (remember, facebook won't necessarily confirm what their email is for you)
and therefore gain access to the existing local account
So, once the merge "request" is made, you need to ask for permission to proceed from the target account of the merge.
The MVC 4 AccountController
I will use Facebook as our OAuth example. To compare what happens when you register a user on your local authentication framework vs. OAuth:
Local: creates an entry in webpages_Membership and an entry with the same UserId in UserProfile (assuming you are using the default tables for the MVC 4 application template)
OAuth: creates an entry in webpages_OAuthMembership and an entry with the same UserId in UserProfile
Now let's look at what happens when a user signs in using Facebook for the first time:
They click on Login using Facebook (or whatever your button says)
they get taken to facebook to login
they succeed (let's assume that, and ignore the failure case)
they then get sent, invisibly to them, to /Account/ExternalLoginCallback
OAuthWebSecurity.SerializeProviderUserId is called, passing the OAuth details to that Action
They get redirected to /Account/ExternalLoginConfirmation and asked to provide a username for their new presence on your site
If that user name is available then UserProfile and webpages_OAuthMembership entries are created
This process is your chance to "join" the accounts by matching some unique piece of information. As long as you end up with the same UserId in UserProfile, webpages_Membership and webpages_OAuthMembership you should be ok. So we have to intercept the process at the point of /Account/ExternalLoginConfirmation.
If the OAuth provider has sent back a matching identifying piece of information, such as an email address, this becomes simple, test for this in the ExternalLoginConfirmation action, and auto-merge using a similar process to the one outlined below.
However, I think you can't/shouldn't assume that the user uses the same email address for your site and OAuth, (nor should you for many reasons). Also, probably in the T&Cs for something like FacebOogLiveWitter it stops you asking for the email of their account anyway, and if they don't currently they might in future.
So instead, you could link the accounts based on alternatives, like username or email address, or phone number. Either way you are going to need them to input some identifying piece of information that is unique against an account, and will pull back the target account.
Wrapping up
So to put this all together: In the first part of this answer I outlined how you will need to consider multiple user journeys to merge accounts. I will use the example 4.1.
Your process will need to:
(Assumption - when a user first registers with a local account, you ask them for an email address and validate it or assume it is valid)
Let the user login with facebook for the first time
at Account/ExternalLoginConfirmation ask them if they want to
Create a new account with you
Use their facebook login to access an existing account
Assuming the latter, then you log a request in a new table (maybe "MergeAccountRequests") with:
The facebook account UserId
The target merge local account UserId
An authorisation code to use in the email you need to send
(From this point on, if they login without confirming that merge, they will have to get sent to a page to ask them to confirm, rather than create objects in other db tables which you have to worry about later)
You then send an email to the address of the target merge (local) account asking for permission to complete the merge (a standard confirmation email, with a link)
When they click on that link, or enter the code you sent them (you could use SMS as well as email) then you need to merge the two accounts
Choose the "new" and "target accounts (in this case "new" is the facebook account as you don't have data associated with it yet)
Delete the UserProfile of the "new" account
Change the UserId of the "new" account webpages_OAuthMembership table to the same as the "target" account
Log the user out (so there are no complications depending on which account they are currently logged in with)
Display a message to the user telling them the merge is almost complete and that they can now log in with either account to confirm and complete the merge
Rather than send them to a login page, i would give them the login options alongside the confirmation message.

CFML: Authenticated user being matched on third party forum plugin so he is 'logged in'

Alright here is the situation.
I have been tasked at my work to integrate a coldfusion forum (Galleon) into the existing CRM that are using for the merchants.
The issue is, the original CRM itself has its own login and a 'user' table in the database. Galleon uses its own login page and 'user' file..
My partner and I on this are racking our brains trying to figure out this (admittedly simple) problem. We thought about the possibility of defining a global variable, like a session, and once triggered by the primary login for the CRM it would bypass the Galleon login.
But this doesn't solve the problem of telling Galleon who the user is so he can post..
I'm thinking one of the ways to solve this issue is to insert the entirety of the original CRM user file into the Galleon user file. That way it has a list of identical user\passes.
Any ideas guys?
Breakdown:
User logins in at CRM splash page----->Brought to CRM index.cfm\main panel. User can then click on "CRM FORUM!" and instead of being re prompted for a user\pass Galleon knows who he is and allows him to make threads and post.
There are definitely a number of ways to skin the cat on this. I downloaded the Galleon 2 forum code to take a peek at the user.cfc
You could modify the query in this function to pull the fields it requires from your CMS:
<cffunction name="getUser" access="public" returnType="struct" output="false" hint="Returns a user.">
<cfquery name="qGetUser" datasource="#variables.dsn#">
SELECT
[cmsusertable].cmsid as ID,
[cmsusertable].cmsuser as username,
[cmsusertable].cmspassword as password,
[cmsusertable].cmsemail as emailaddress,
[cmsusertable].createDate as datecreated,
[cmsusertable].cmsactive as confirmed,
[cmsusertable].cmssignature as signature,
[cmsusertable].cmsavatar as avatar
FROM
[cmsusertable]users
WHERE
[cmsusertable].username = <cfqueryparam value="#arguments.username#" cfsqltype="CF_SQL_VARCHAR" maxlength="50">
</cfquery>
Remember that you must return the fields from the query as Galleon expects them, so use the 'as' statement to rename your CMS database fields to what Galleon expects. Now some of these extraneous fields you might not have in your CMS table such as Signature / Avatar. If you can extend your CMS table and user routines to accommodate these fields, that might be good. Or you could modify the profile routines in Galleon to only update the Signature/Avatar instead of the whole profile. If you do use the Galleon tables to store this information, remember to add a join to include these fields where requested to reunify the user data.
You'll also have to modify the joins in about 4 files (user.cfc, conference.cfc, message.cfc, thread.cfc) in the project to join with your CMS user table instead.
Lastly, you'll have to modify the the login.cfm to simply attempt to set the session.user struct using the information in the CMS user session and failing that, redirect the user back to the CMS login page.
Overall I don't think it would be too difficult. I'm sure there's stuff I missed but perhaps that would get you going.
What you described is exactly how many sites work, regardless of the mechanism you use to authenticate (i.e.; OAuth, Twitter, etc.) You use the external service for authentication, and you get back a token of some kind from that external service that says "This person really is authenticated." It's up to your code -- Galleon in this case -- to say "This person is authenticated, but they don't have an account in our system. Let's make one." This usually requires you to go back to the external service to get a name, email address, etc.
You will most likely have to do some additional work in your external service to allow for updates of customer information in Galleon. If, for example, someone changes their email address, there's more than likely an email address in Galleon which should also be updated. This can get complicated, but is a necessity from the customer's point of view.
The best way to do this would be to sync up your Galleon forum user table with your CRM, then keep them in sync as you add/remove/update CRM users.
The key to doing this is by utilizing the Galleon business layer API-- a.k.a. the public methods in the Galleon CFCs. This will keep you from having to modify ANY of Galleon's code, which I would highly recommend if you'd like to easily install Galleon updates. (By the way, you should keep your 3rd party codebase up to date, since open source projects are popular targets for hackers-- especially forums.)
To sync up your existing users, you'll want to write a script that iterates through your current CRM's users and calls Galleon's User.addUser() method for each user, using the same user/pass combo as your CRM (or maybe use hashes of them). Be sure to break on any Galleon errors/failures so you don't miss any users.
To keep Galleon in sync with your CRM, add calls to Galleon's CFCs as needed. For instance, call User.deleteUser() when you delete a user from your CRM.
For authentication, you'll use User.authenticate(), passing in the same user/pass combo as your CRM.
Utilizing the business-layer API of 3rd-party libraries is a much better long-term solution than trying to modify them to suit your needs.

How does stackoverflow maintain a database of Open-id signed-in users?

I will like to know how does Stackoverflow maintain the additional details of users logging in using open-ids? In my knowledge, the details of these users are stored in the server of google,facebook etc. (The ones whose open id is being used). How then this site is also storing info about user's points, badges, privileges etc.?
Open id Selector, the one being used by Stackoverflow, is a client side javascript library so how is this possible?
Is a separate database created? If yes, how? There is no registration even!
Please provide the details of how this is being done.
When you login, the server checks if you already have an account. If there is no entry (it is the very first login), the server will automatically create a new user and save the openid identifier.
So the next time you login, the row is already there, and Stack Overflow will recognize you. By the way, you can learn the id of your database entry by looking at your profile url.
The JavaScript openid-selector is not involved in any of this. It just is a convenience feature which allows easy selection of an openid provider. All its magic is done before the openid magic takes place.