Set Password email by application - fusionauth

I have 2 applications on the same Tenant.
I can configure an email template for the "Set Password" workflow on:
an Application Level
the Tenant level
When I register a new user using the UI, as far as I understood it will only be able to send the email configured on the tenant level since it won't know anything about which application the user can see until the next step when I add the registrations.
If I create a user and add registration to it right away (on the same step) then this takes the Template configured on the application level.
My questions are:
Can we do something like this through the UI interface too? My applications have a different user base (some have accounts on both) and it would be nice to be able to send them one email or the other.
Or is this only possible through the API?
If I register a user with both applications (through the API) which email do they get?
Thanks for the help!

Can we do something like this through the UI interface too?
This is not currently possible. Creating the User, and creating a User Registration are two separate steps. As you correctly stated, when creating the user in the UI, there is no context yet for an application. For this reason, the user will receive the template configured at the tenant level.
Or is this only possible through the API?
Correct. You must use the Create "User + Registration" API to do this in one step to use the application template for setup password.
If I register a user with both applications (through the API) which email do they get?
When using the API to Create "User + Registration" you can only register for one application at a time. The email is only sent during the User Create step, so if you register for a second application, the user will already exist and thus will not receive a second email.

Related

Managing email templates in FusionAuth

We are integrating FusionAuth into our user account / profile system for 3 SaaS apps. We'll have about 5 roles established and the onboarding process for each such user is different.
A new user signup could be brand new, could be existing but for a new role, or could be reactivation of an account. So roughly speaking we might need to establish 3 x 5 x 2 (new and returning user) emails for account verification and then the same number of welcome emails. Each email will have specific instructional text, email subject, and links.
The ability to duplicate email templates in the FusionAuth UI would be useful but clearly this isn't a complete solution. If I create multiple tenants to support our development, testing and production releases - it would really be great to be able to maintain a master list of versioned templates and to link any one of those email template versions to any tenant and app.
If you are familiar with SendGrid - the versioned templates there are pretty nice, as is the conditional logic that can be used in the templates to reduce the total number of documents that must be maintained.
For my sanity and for the maintenance burden associated with these emails, I'd like to use only FusionAuth or only SendGrid for these account maintenance emails. Since SendGrid is the more robust email solution it might be the better choice.
What can be accomplished with FusionAuth's User Actions? Can all FusionAuth email templates can be disabled from the FusionAuthUI and API?
Adding a user from our UI will require creating (or returning) the FusionAuth user, setting the FusionAuth App registration, setting the role, then triggering the necessary email.
It could be really cool if all that can be configured as a multistep User Action that creates / updates and configures the user and then triggers the SendGrid template email.
The versioning and duplicate options for email templates are great ideas. FusionAuth does not currently support email template versioning or copy / duplicate in the UI. Can you open these as feature requests in GitHub? https://github.com/FusionAuth/fusionauth-issues/issues
We do support conditional logic within the template. There is a brief tutorial in the FusionAuth docs. https://fusionauth.io/docs/v1/tech/email-templates/email-templates
To build conditional logic you can use essentially anything that FreeMarker supports. https://freemarker.apache.org/
For example
[#if user.data.favoriteColor == "blue"]
Hi ${user.firstName}, I see you like the color blue.
[#else]
Hi ${user.firstName},
[/#if]
If you have some particular use cases or need some help building the logic in your template feel free to ask for help in the FusionAuth Slack channel or ask here.
That said - SendGrid is in the email game, they will likely have some powerful features not available in FusionAuth. If you require many power user features, I wouldn't try to dissuade you from using SendGrid. But do open feature requests so we can make our email templates as useful as possible.
What can be accomplished with FusionAuth's User Actions?
User actions are sort of free form events that will be sent using our Webhook configuration. They can only be taken on a user that already exists in FusionAuth, so it may not be the right fit for your use case. In addition to User Actions, you can enable events such as user.create, etc - so you can respond to these types of events in FusionAuth if that is helpful.
Can all FusionAuth email templates can be disabled from the FusionAuthUI and API?
Not sure what you mean - you can disable the SMTP email configuration which implicitly disables all use of email. This can be done via the System Configuration API. https://fusionauth.io/docs/v1/tech/apis/system#update-the-system-configuration See systemConfiguration.emailConfiguration.enabled. FusionAuth is an API first, so everything you can do in the API you can do through an API.
It could be really cool if all that can be configured as a multistep User Action that creates / updates and configures the user and then triggers the SendGrid template email.
User Actions will not help with this use case. However, you may be able to accomplish this in fewer API calls. If you know the user does not yet exist, you can use the Combo API (Create User + Registration) to create and register the user in one step. https://fusionauth.io/docs/v1/tech/apis/registrations#create-a-user-and-registration-combined
If you omit the roles from this request, the user will be assigned any default roles configured on the application.
If you enable Registration Verification, this will send the user an email of your choosing. This is primarily intended to verify the user intended to register for the application.
The custom workflow idea is a good one however, feel free to open an issue on GitHub. I would envision it as a work flow builder for an application.
Example:
On user registration:
1. Assign role(s): [x] user
[ ] manager
[ ] admin
2. Send email: [select box for email template]

How to avoid script authorization prompt when G-Suite user is accessing G-Suite trusted app script?

I wrote an app script which provides a web UI for data entry into a team calendar. I published it using G-Suite super admin account and added it as Trusted App under Security/API Permissions. "Trust domain owned apps" is checked under "Internal App Settings".
When a G-Suite user in our organization tries to access the app, he sees
"The developer of ShiftSchedulingApp, admin#_our_organization_.org, needs your permission to access your data on Google."
Those brave enough to click "Review Permissions" are taken to the next message:
"ShiftSchedulingApp wants to access your Google Account. See, edit, share, and permanently delete all the calendars you can access using Google Calendar"
Of course nobody wants to risk losing all the calendars on their Google Account and this is where it ends.
How do I get rid of this misleading message? It's not Google account, it's their organization account on G-Suite. It's not all their calendars, it's the shared team calendar only. It's adding data, not permanently deleting calendars. It's published by their administrator in their G-Suite, not an unknown 3rd party.
I spent days trying to make this message go away but no luck. App must be executed as an accessing user and not as publishing user because their user ID determines what shifts they can fill on a calendar.
I'd appreciate any hints pointing me the right direction.
I experimented with variations of the two-app approach as suggested.
The app which provides the UI needs to read the calendar to display available shifts - so I can't get away from the user authorization prompt.
Another variation I tried was having one app do everything and run as me, and another do nothing but return Session.getActiveUser(). I tried calling the 2nd one from the 1st one on the client side via XMLHttpRequest. It would be ideal for my needs - but I hit CORS error as apps URL is script.google.com but it actually gets redirected to script.googleusercontent.com. There doesn't seem to be a way to set CORS in Google App Script.
Although I was not able to find a way to avoid prompting users for authorization when executing the app as accessing user, it turns out my reasons for doing that were based on a false premise.
I chose to publish app as accessing user because I thought that's the only way to get accessing user Id - which is true for non-G Suite accounts.
However, when app is published by a G Suite account, the app can get accessing user ids within the same G Suite domain even when it's set to execute as publishing user.
Thanks Niek and TheMaster for your help!
If you just need user ID, why do you ask for all those permissions?
Possible Solutions:
2 web-apps- One running as you and another as user accessing (with only profile) permission. The second one will be the actual web interface and POST necessary information to the first one with privileges. OR
Implement your own web-app Google-sign in1
Use the least permissive2 scope3

Adding arbitrary objects in the OpenFire Session

We have an existing OAuth2 based website. Our plan is to use a web based (XMPP over websockets) chat system.
now this chat system will be available once the user logs in. What we actually do not want is to login twice, once for the web site and once for the chat system.
So I figured how to trick it with my own auth provider and a custom username/password.
So basically the question is how do I have an object that I want to travel along with the user chat session so that I can provide out of band processing.
Does the session management allow this?
In a similar use-case, there I need to persist and store various pieces of information about a user, in Openfire, so that external calls and look-ups are not necessary during later, custom logic in an Openfire plugin. It is possible to add any number of custom properties to an openfire user, via REST, or other APIs.
Then, those custom properties can be retrieved as needed, without external calls.
create user api
Then, if using Internal APIs, you get
Get the session's username or address (JID)
call UserManager's getUser on the username or JID to get the User object
call User's getPropertyValue to get a specific property or getProperties to retrieve all custom user properties

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.

Spring. Java. Log in and activation email

I have a "chicken egg" problem.
In application I use UserDetailsService to get User (we don't store user information in our DB, we use third party service to actually get all information).
Recently we've added account activation feature. After registration, we send an activation email to a user and if he clicks on it, we mark the User as ACTIVE and redirects him to log in page. User can login only if he has ACTIVE status. The problem is: we'll start charging user from the date he activates his account even if he never logs in. How can I (maybe using spring security) make those processes (activation and login) almost simultaneous? We don't want to charge user if he just activates his account, we want to charge him only if he has logged in (after activation). So can I actually do it somehow "user clicks activation link, login and then his status is changed to ACTIVE (but he can login only if he is ACTIVE)".
Sorry if my problem description isn't clear enough
I'll appreciate any feedback.
Thanks!
If I understood your requirements correctly, you'll need two different entry points (login pages) to your application:
One for activation (first login) for users not yet activated.
Another "normal" one for active users.
The problem is that the authentication logic would need to be context sensitive and be aware of which of the above pages initated the authentication. However the framework was not designed for such uncommon use-cases, so the authentication provider has no knowledge about the URL from which the login-form were actually sent.
What you need to solve is to somehow relay contextual information to an authentication provider that processes the auth request according to that information (i.e. authenticate only non-active users logging in from url1, and authenticate only active users logging in from url2). There could be hundreds of different ways to achieve this, one possible solution is to put two different authenentication filters in place that intercept auth requests sent to the two different urls. Details outlined below:
Create your own custom versions of the existing WebAuthenticationDetailsSource and WebAuthenticationDetails (preferably by subclassing the latter) that stores and exposes the URI of the authentication request. (That will be the contextual information based on which the auth provider can implement its conditional logic.)
Configure and insert two different instances of the UsernamePasswordAuthenticationFilter in the filter chain. Set their filterProcessesUrl attribute to /j_spring_security_check_active_user and /j_spring_security_check_nonactive_user respectively, plus inject the above created custom AuthenticationDetailsSource in both of them.
Override DaoAuthenticationProvider.additionalAuthenticationChecks() in a subclass in the following way:
Retrieve the URI stored in the above created WebAuthenticationDetails object (it's accessible via authentication.getDetails())
Assert that the user is active/non-active according to the URI, and throw an AccountStatusException if the asserion fails.
Don't forget to delegate to the superclass if the assertion succeeds.
Create the two different login pages mentioned at the beginning of the post, making sure that the login forms post credentials to their respective URL (/j_spring_security_check_nonactive_user vs. /j_spring_security_check_active_user).