Announced yesterday in preview, email one-time passcodes (OTP) expand the range of authentication mechanisms available for Azure Active Directory guest accounts. Today, when you invite someone from outside your tenant to access a resource or application, Azure Active Directory issues that person with an invitation. When they redeem the invitation, they must create a Microsoft account to authenticate, unless they already have an Azure Active Directory account (for instance, in another Office 365 tenant), a Microsoft account (for instance, in Outlook.com), or they have a Google account and the tenant supports Google as an identity provider.
Creating a Microsoft account isn’t a big deal, but the person redeeming the invitation might consider it unnecessary as they already have an account. Given the profusion of accounts needed to access internet sites, creating another that is only ever used to access resources in your tenant could be seen as a burden. OTP removes the issue by allowing the invitee to redeem the invitation and access the resource in your tenant without having to create a Microsoft account. The experience is more seamless because the invitee continues to use their normal account.
Blocking Unwanted Sharing
Microsoft says that OTPs open up collaboration to anyone who has an email address. You might not want users to share with just anyone, so remember that you can configure blocked domains in the Azure B2B Collaboration policy. And of course, you can use conditional access policies to control how guest users access content.
Setting Up OTP
Setting up a tenant to support OTP involves updating the Azure B2B Management policy with PowerShell. Connect to Azure AD and paste the commands listed in the documentation into the command window to update the policy. Give Azure AD a couple of minutes to refresh and make the updated policy effective. Afterwards, any invitation generated to an email address that can’t be matched against an Azure AD instance, an MSA domain (like live.com), or Google (if configured) will use an OTP.
When the recipient redeems the invitation and connects to your tenant to access a resource, they see that a code is used. The code is generated and sent to the email address and then input to a challenge screen to authenticate the user.
OTP code will be sent
Authentication for a Day
Authentication granted through an email OTP lasts 24 hours. The idea here is that users must be able to prove their identity to continue to access your resources, and they do this by processing the OTP sent to their mailbox when authentication is necessary.
During the 24-hour authentication period, the user’s access is like as if they had authenticated by signing in. They are not prompted to reauthenticate if they move between applications and resources in a browser session.
Guest Accounts Still Needed
An external user who authenticates with OTPs still needs a guest account in your tenant. The difference is that instead of being marked as having its source as “External Azure Active Directory” or “Microsoft Account,” the source is OTP. You can see this information in the Azure Active Directory portal.
Guest account that uses OTP
Unfortunately, I can’t find anything in the properties returned by Get-AzureADUser to be able to highlight OTP guests through PowerShell.
Using OTP with Office 365 Applications
External access to Office 365 applications like Groups, Teams, and Planner have driven the use of Azure Active Directory guest accounts in many tenants. You can’t use OTP authentication for these applications today. and will see sign-in errors about “no tenant-identifying information” if you try.
Can’t use OTP to sign into Teams
Microsoft explains this in their documentation by noting that “one-time passcode users must sign in using a link that includes the tenant context, for example https://myapps.microsoft.com/?tenantid=<tenant id>“. Like any new feature (especially those in preview), it takes time for production applications to catch up and support. Teams will have to update its code to deal with desktop and mobile applications as well as browsers, while Planner needs to update its sign-in process and links to support OTP guests.
Sharing with SharePoint
In testing OTP, I was able to use an account authenticated with OTP to access documents shared with the account from SharePoint Online or OneDrive for Business, which seem to include some tenant context in their URLs. Likewise, I was able to access the document library belonging to an Office 365 group when the account using OTP was added as a member of the group. However, the success was transient. The links depend on the client already being authenticated in the tenant and if this is the case, they can open documents shared with them. The problem is that the passcode expires after a day. If the user then tries to reuse a sharing link, they won’t be able to access the document because they are no longer authenticated and there doesn’t seem to be a way to force Office 365 to regenerate a passcode to regain access. Microsoft’s Maria Lai says in a comment to the announcement that OTP “will replace the one-time passcode sent in SharePointsoon.” I don’t know when the replacement will happen, but the delay is likely to allow SharePoint Online to include some code to send passcodes to people when their tokens expire.
As guests communicate with other members in an Office 365 group via email, the fact that they can access the group’s document library might make it seem that Outlook groups seem to support OTP. However, as not above, access to the document library only lasts for the lifetime of an authentication token. So Outlook groups will need the work done by SharePoint before they can support OTP access for guest users.
One-time Passcodes and Office 365
I’m not sure how important OTP will be for Office 365. Obviously, Office 365 has a set of applications which support external access that need to be updated for OTP, but when access is considered for someone outside the company, those controlling the resources might prefer to use another authentication method. We’ll see in time. Meantime, if you do use OTP and need to switch a guest to another authentication method, remember that this is only possible by removing the guest account and reissuing an invitation.
We cover how to manage guest user accounts in Chapter 12 of the Office 365 for IT Pros eBook. We’ll update that section when the Office 365 apps support OTP authentication.
11 Replies to “Email One-Time Passcodes for Azure Active Directory”
Thanks for your coverage above Tony. PowerShell is definitely an option for opting into the preview, but there is a UI button you can click too 😉
What did you think about this line in the documentation you linked to – “When a user redeems a one-time passcode and later obtains an MSA, Azure AD account, or other federated account, they’ll continue to be authenticated using a one-time passcode. If you want to update their authentication method, you can delete their guest user account and reinvite them.” I would prefer a more self-healing / self-updating approach as identity accounts change for the guest user over time.
I’d prefer a self-healing mode too… and as I noted earlier, this is the kind of thing that will probably happen as Microsoft moves towards general availability.
The other thing I found “interesting” is this line in the email with the account verification code: “If you didn’t request a code, you can ignore this email.” Well, actually, if you didn’t request a code, someone else has gained access to an invitation that was destined for you, and has used that invitation to attempt to log into a specific resource using your identity. If you didn’t request it, and that flow has happened, you should be VERY concerned about account credential compromise, etc.
It will be interesting to see how that’s reworded. Thanks for the feedback. And it must be late where you are … so sleep well.
Loading...
Thanks for your article and your testing of this new feature. Is there an update on this topic? Like which O365 applications today (june 2020) can work with OTP?
Maybe i will subscribe. Allthough it is not in my native language. I am planning on testing OTP myself but need to know if it it works with Teams for membership invitations and webinar invitations. The only thing we probably need it for is the webinar invitations to offer participants an easy way to log into the webinar.
{"id":null,"mode":"button","open_style":"in_modal","currency_code":"EUR","currency_symbol":"\u20ac","currency_type":"decimal","blank_flag_url":"https:\/\/office365itpros.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/blank.gif","flag_sprite_url":"https:\/\/office365itpros.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/flags.png","default_amount":100,"top_media_type":"featured_image","featured_image_url":"https:\/\/office365itpros.com\/wp-content\/uploads\/2022\/11\/cover-141x200.jpg","featured_embed":"","header_media":null,"file_download_attachment_data":null,"recurring_options_enabled":true,"recurring_options":{"never":{"selected":true,"after_output":"One time only"},"weekly":{"selected":false,"after_output":"Every week"},"monthly":{"selected":false,"after_output":"Every month"},"yearly":{"selected":false,"after_output":"Every year"}},"strings":{"current_user_email":"","current_user_name":"","link_text":"Virtual Tip Jar","complete_payment_button_error_text":"Check info and try again","payment_verb":"Pay","payment_request_label":"Office 365 for IT Pros","form_has_an_error":"Please check and fix the errors above","general_server_error":"Something isn't working right at the moment. Please try again.","form_title":"Office 365 for IT Pros","form_subtitle":null,"currency_search_text":"Country or Currency here","other_payment_option":"Other payment option","manage_payments_button_text":"Manage your payments","thank_you_message":"Thank you for supporting the work of Office 365 for IT Pros!","payment_confirmation_title":"Office 365 for IT Pros","receipt_title":"Your Receipt","print_receipt":"Print Receipt","email_receipt":"Email Receipt","email_receipt_sending":"Sending receipt...","email_receipt_success":"Email receipt successfully sent","email_receipt_failed":"Email receipt failed to send. Please try again.","receipt_payee":"Paid to","receipt_statement_descriptor":"This will show up on your statement as","receipt_date":"Date","receipt_transaction_id":"Transaction ID","receipt_transaction_amount":"Amount","refund_payer":"Refund from","login":"Log in to manage your payments","manage_payments":"Manage Payments","transactions_title":"Your Transactions","transaction_title":"Transaction Receipt","transaction_period":"Plan Period","arrangements_title":"Your Plans","arrangement_title":"Manage Plan","arrangement_details":"Plan Details","arrangement_id_title":"Plan ID","arrangement_payment_method_title":"Payment Method","arrangement_amount_title":"Plan Amount","arrangement_renewal_title":"Next renewal date","arrangement_action_cancel":"Cancel Plan","arrangement_action_cant_cancel":"Cancelling is currently not available.","arrangement_action_cancel_double":"Are you sure you'd like to cancel?","arrangement_cancelling":"Cancelling Plan...","arrangement_cancelled":"Plan Cancelled","arrangement_failed_to_cancel":"Failed to cancel plan","back_to_plans":"\u2190 Back to Plans","update_payment_method_verb":"Update","sca_auth_description":"Your have a pending renewal payment which requires authorization.","sca_auth_verb":"Authorize renewal payment","sca_authing_verb":"Authorizing payment","sca_authed_verb":"Payment successfully authorized!","sca_auth_failed":"Unable to authorize! Please try again.","login_button_text":"Log in","login_form_has_an_error":"Please check and fix the errors above","uppercase_search":"Search","lowercase_search":"search","uppercase_page":"Page","lowercase_page":"page","uppercase_items":"Items","lowercase_items":"items","uppercase_per":"Per","lowercase_per":"per","uppercase_of":"Of","lowercase_of":"of","back":"Back to plans","zip_code_placeholder":"Zip\/Postal Code","download_file_button_text":"Download File","input_field_instructions":{"tip_amount":{"placeholder_text":"How much would you like to tip?","initial":{"instruction_type":"normal","instruction_message":"How much would you like to tip? Choose any currency."},"empty":{"instruction_type":"error","instruction_message":"How much would you like to tip? Choose any currency."},"invalid_curency":{"instruction_type":"error","instruction_message":"Please choose a valid currency."}},"recurring":{"placeholder_text":"Recurring","initial":{"instruction_type":"normal","instruction_message":"How often would you like to give this?"},"success":{"instruction_type":"success","instruction_message":"How often would you like to give this?"},"empty":{"instruction_type":"error","instruction_message":"How often would you like to give this?"}},"name":{"placeholder_text":"Name on Credit Card","initial":{"instruction_type":"normal","instruction_message":"Enter the name on your card."},"success":{"instruction_type":"success","instruction_message":"Enter the name on your card."},"empty":{"instruction_type":"error","instruction_message":"Please enter the name on your card."}},"privacy_policy":{"terms_title":"Terms and conditions","terms_body":null,"terms_show_text":"View Terms","terms_hide_text":"Hide Terms","initial":{"instruction_type":"normal","instruction_message":"I agree to the terms."},"unchecked":{"instruction_type":"error","instruction_message":"Please agree to the terms."},"checked":{"instruction_type":"success","instruction_message":"I agree to the terms."}},"email":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email address"},"success":{"instruction_type":"success","instruction_message":"Enter your email address"},"blank":{"instruction_type":"error","instruction_message":"Enter your email address"},"not_an_email_address":{"instruction_type":"error","instruction_message":"Make sure you have entered a valid email address"}},"note_with_tip":{"placeholder_text":"Your note here...","initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"empty":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"not_empty_initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"saving":{"instruction_type":"normal","instruction_message":"Saving note..."},"success":{"instruction_type":"success","instruction_message":"Note successfully saved!"},"error":{"instruction_type":"error","instruction_message":"Unable to save note note at this time. Please try again."}},"email_for_login_code":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email to log in."},"success":{"instruction_type":"success","instruction_message":"Enter your email to log in."},"blank":{"instruction_type":"error","instruction_message":"Enter your email to log in."},"empty":{"instruction_type":"error","instruction_message":"Enter your email to log in."}},"login_code":{"initial":{"instruction_type":"normal","instruction_message":"Check your email and enter the login code."},"success":{"instruction_type":"success","instruction_message":"Check your email and enter the login code."},"blank":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."},"empty":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."}},"stripe_all_in_one":{"initial":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"empty":{"instruction_type":"error","instruction_message":"Enter your credit card details here."},"success":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"invalid_number":{"instruction_type":"error","instruction_message":"The card number is not a valid credit card number."},"invalid_expiry_month":{"instruction_type":"error","instruction_message":"The card's expiration month is invalid."},"invalid_expiry_year":{"instruction_type":"error","instruction_message":"The card's expiration year is invalid."},"invalid_cvc":{"instruction_type":"error","instruction_message":"The card's security code is invalid."},"incorrect_number":{"instruction_type":"error","instruction_message":"The card number is incorrect."},"incomplete_number":{"instruction_type":"error","instruction_message":"The card number is incomplete."},"incomplete_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incomplete."},"incomplete_expiry":{"instruction_type":"error","instruction_message":"The card's expiration date is incomplete."},"incomplete_zip":{"instruction_type":"error","instruction_message":"The card's zip code is incomplete."},"expired_card":{"instruction_type":"error","instruction_message":"The card has expired."},"incorrect_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incorrect."},"incorrect_zip":{"instruction_type":"error","instruction_message":"The card's zip code failed validation."},"invalid_expiry_year_past":{"instruction_type":"error","instruction_message":"The card's expiration year is in the past"},"card_declined":{"instruction_type":"error","instruction_message":"The card was declined."},"missing":{"instruction_type":"error","instruction_message":"There is no card on a customer that is being charged."},"processing_error":{"instruction_type":"error","instruction_message":"An error occurred while processing the card."},"invalid_request_error":{"instruction_type":"error","instruction_message":"Unable to process this payment, please try again or use alternative method."},"invalid_sofort_country":{"instruction_type":"error","instruction_message":"The billing country is not accepted by SOFORT. Please try another country."}}}},"fetched_oembed_html":false}
Thanks for your coverage above Tony. PowerShell is definitely an option for opting into the preview, but there is a UI button you can click too 😉
What did you think about this line in the documentation you linked to – “When a user redeems a one-time passcode and later obtains an MSA, Azure AD account, or other federated account, they’ll continue to be authenticated using a one-time passcode. If you want to update their authentication method, you can delete their guest user account and reinvite them.” I would prefer a more self-healing / self-updating approach as identity accounts change for the guest user over time.
I’d prefer a self-healing mode too… and as I noted earlier, this is the kind of thing that will probably happen as Microsoft moves towards general availability.
We wait and watch with interest indeed.
The other thing I found “interesting” is this line in the email with the account verification code: “If you didn’t request a code, you can ignore this email.” Well, actually, if you didn’t request a code, someone else has gained access to an invitation that was destined for you, and has used that invitation to attempt to log into a specific resource using your identity. If you didn’t request it, and that flow has happened, you should be VERY concerned about account credential compromise, etc.
This is a preview and you point to the kind of details that Microsoft need to smoothen and improve as they drive towards general availability.
It will be interesting to see how that’s reworded. Thanks for the feedback. And it must be late where you are … so sleep well.
Thanks for your article and your testing of this new feature. Is there an update on this topic? Like which O365 applications today (june 2020) can work with OTP?
Still in preview https://docs.microsoft.com/en-us/azure/active-directory/b2b/one-time-passcode SPO and OneDrive for Business support OTP for sure.
Maybe you should subscribe to Office 365 for IT Pros and keep updated of changes like this… it’s in Chapter 3 of the book.
Maybe i will subscribe. Allthough it is not in my native language. I am planning on testing OTP myself but need to know if it it works with Teams for membership invitations and webinar invitations. The only thing we probably need it for is the webinar invitations to offer participants an easy way to log into the webinar.
I believe some people are testing OTP with Teams. I have not tried it myself.