
みなさんこんにちは! 最近、バックエンドでモバイルアプリケーションのユーザーを認証する問題を解決しています。 だから、あなたが尋ねる、タスクはすでに千回解決されています。 この記事では、成功の話をしません。 集めたレーキについて教えてください。
プロジェクトについて少し
2GISでは、企業のクールで正確なディレクトリを作成します。 2GISのデータの品質と関連性を確保するために、いくつかの内部システムがあります。 それらの1つはYouLaと呼ばれます-いいえ、広告が公開されるものではありません。 YouTubeのYouLaは、地上でデータを調整するプロセスをサポートしています。
システムの一部は、歩行者が歩くモバイルアプリです。 歩行者は街全体を回る専門家です。 マップは、確認のために異なるセクションに分割されています。
モスクワ地方の領土区分がどのように見えるかをご覧ください。 マップ上の異なる色は、異なる目的地を示しています。

歩行者は、電話をかけられない組織やウェブサイトがない組織に関する情報をもたらします。 たとえば、バーベキュー、野菜の屋台。 さらに、組織が電話を変更したため、そこを通過できません。 上記のすべてのケースで、当社のスペシャリストが組織に来て、現場で情報を確認します。
ほんの数日前に、データ同期のバックエンドを作成する新しいモバイルアプリケーションを立ち上げました。
新しいバックエンドでは、どのようなユーザーが来たのかを知りたいと思っています。
承認にはいくつかの要件があります。
-信頼性と安全性、
-さまざまなソースからの認証、
-いくつかのタイプのクライアントWeb、モバイル、APIの認証。
認証方法の選択
認証の実装にはさまざまなアプローチがあり、それぞれに長所と短所があります。 多数の統合ポイントがあるため、
車輪を再発明せず、OpenId Connectに基づいた認証および承認プロバイダーを採用することにしました。 バックエンドでの承認には、JWTを使用します。
詳細については、「 マイクロサービスアプリケーションでの認証と承認 」をご覧ください。
JWTとエンタープライズのOpenId Connect標準の利点は何ですか?
現在、1つの会社のフレームワーク内であっても、システムはさまざまなテクノロジースタックで開発されており、後で友人を作ることは難しい場合がよくあります。 1つのテクノロジースタック内で、多くの奇妙で予想外の効果をキャッチすることもでき、複数のシステムがある場合の状況は言うまでもありません。 JWTおよびOpenId Connectの場合、サポートされるクライアントとプラットフォームのリストは印象的です。
すべてのコンポーネントの操作スキームは次のようになります。

このプロトコルは、認証プロバイダーの動的接続をサポートしています。 Google+とADFSの2つのソースを調べました。 しかし、将来的には、たとえば、システムの問題を解決できるシステムに他の企業を接続することにより、製品の対象者を簡単かつ迅速に拡大したいと考えています。
JWTを使用すると、多彩なクライアントの認証を簡単に整理できます。 さらに、多くのクラウドクライアントは、アプリケーションへのプロバイダーの統合を促進するライブラリセット全体をすぐに提供します。
クラウドソリューション
私たちが試した最初のプラットフォームはAuth0です。 プラットフォームは、開発者と管理者の両方にとって非常にクールです。 詳細なドキュメント、すべてのパラメーターを設定するための美しく直感的なWeb UIがあります。 Java / Kotlinアプリケーションとバックエンドでは、認証は数時間で完了しました。
Auth0プラットフォームで作業するときに注意した主な利点:
-一般的なプログラミング言語の詳細なドキュメントと無限のコードサンプル。
-認証に使用する機能は、Webではなく、ネイティブのログインフォームです。
バックエンドでJWT認証のサポートを実装するには、ほんの数行を書くだけで十分です(異なるプラットフォームのこのコードはAuthorityおよびAudienceパラメーターのみが異なります)。場合によっては、トークン署名を検証する証明書も指定する必要があります。
.NET Coreバックエンドコードpublic void ConfigureServices(IServiceCollection services) { services.AddMvc();
携帯電話への認証を固定するために-さらにいくつかの行:
携帯電話のログインコード private void login() { token.setText("Not logged in"); Auth0 auth0 = new Auth0(this); auth0.setOIDCConformant(true); WebAuthProvider.init(auth0) .withScheme("demo") .withAudience(String.format("https://%s/userinfo", getString(R.string.com_auth0_domain))) .withScope("openid email profile") .start(MainActivity.this, new AuthCallback() { @Override public void onSuccess(@NonNull final Credentials credentials) { runOnUiThread(new Runnable() { @Override public void run() { idToken = credentials.getIdToken(); accessToken = credentials.getAccessToken(); Log.d("id token", credentials.getIdToken()); Log.d("access token", credentials.getAccessToken()); token.setText("Logged in: " + credentials.getIdToken()); } }); } @Override public void onFailure(@NonNull final Dialog dialog) { runOnUiThread(new Runnable() { @Override public void run() { dialog.show(); } }); } @Override public void onFailure(final AuthenticationException exception) { runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, "Error: " + exception.getMessage(), Toast.LENGTH_SHORT).show(); } }); } }); }
この例からわかるように、認証後、2つのトークンが追加され、もう1つ(RefreshToken)はコードに表示されません。
彼らは何のために?
IdToken-ユーザー資格情報が含まれています
AccessToken-APIでの承認用
RefreshToken-AccessTokenの更新用
バックフィルの質問:なぜ2つのアクセストークンとリフレッシュトークンが必要なのですか?
答えキー窃盗の2つのケースを検討してください。
- 悪党はAccessTokenのみを盗みました。 その後、RefreshTokenを使用するまで有効になります。
- 悪党は両方のトークンを盗みました。 その後、彼がRefreshTokenを使用するとすぐに、トークンが機能しなくなり、アプリケーションからログアウトします。 資格情報を使用すると、攻撃者のトークンは機能しなくなります。
2つのトークンを使用すると、攻撃者がAPIにアクセスできる時間が制限されます。
JWT-IdTokenトークン自体は次のようになります。

モバイルアプリケーションは、このトークンから認証済みユーザーに関する情報を受け取ります。 したがって、IdTokenを使用して、ユーザーとそのアバターの名前を描画します。
リクエストのヘッダーに添付するAccessToken:
AndroidアプリケーションからのAPI呼び出し private void makeApiCall() { DevDayApi api = CreateApi("http://rnd-123.2gis.local/", accessToken); api.getUserProfile().enqueue(new Callback<ApiResponse>() { @Override public void onResponse(Call<ApiResponse> call, Response<ApiResponse> response) { runOnUiThread(() -> { if(response.body() != null) apiAnswer.setText(response.body().Answer); }); } @Override public void onFailure(Call<ApiResponse> call, Throwable t) { apiAnswer.setText(t.getMessage()); } }); } private DevDayApi CreateApi(String baseUrl, String authToken) { HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.HEADERS); OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(chain -> { Request newRequest = chain.request().newBuilder() .addHeader("Authorization", "Bearer " + authToken)
Webクライアント認証の場合、IdenitityProviderを介した対話型ログインも非常に簡単です。 以下は、これをAngular4アプリケーションに固定する方法に関する公式ドキュメントの例です。
Webアプリケーションバックエンド認証 import { Injectable } from '@angular/core'; import { AUTH_CONFIG } from './auth0-variables'; import { Router } from '@angular/router'; import * as auth0 from 'auth0-js'; @Injectable() export class AuthService { auth0 = new auth0.WebAuth({ clientID: AUTH_CONFIG.clientID, domain: AUTH_CONFIG.domain, responseType: 'token id_token', audience: `https://${AUTH_CONFIG.domain}/userinfo`, redirectUri: AUTH_CONFIG.callbackURL, scope: 'openid' }); constructor(public router: Router) {} public login(): void { this.auth0.authorize(); } public handleAuthentication(): void { this.auth0.parseHash((err, authResult) => { if (authResult && authResult.accessToken && authResult.idToken) { this.setSession(authResult); this.router.navigate(['/home']); } else if (err) { this.router.navigate(['/home']); console.log(err); alert(`Error: ${err.error}. Check the console for further details.`); } }); } }
例からわかるように、誰も気分を害することはありませんでした-顧客への実装はシンプルで簡単です。
完全に幸福にするために、ローカルActive Directoryによるユーザー認証がありませんでした。
Auth0とローカルActive Directory間の同期を構成するために、Auth0にはPowerShellスクリプトが用意されています。

すべてが正常に機能し、ADとAuth0間の同期をセットアップするようにというリクエストで管理者に問い合わせてくれたことがすでに嬉しかったので、拒否されました。 彼らは、私たちのデータを注ぐ準備ができている最大の場所はAzureだと言いました。 また、この決定は、Office 365サブスクリプションを既に使用しており、一部のアカウントが既にAzureにアップロードされているという事実に影響されました。
さて、言った。
Azure Active Directory B2C
Microsoftには、Azure Active Directory B2Cというサービスがあります。 管理者の助けを借りて、ADとAzure ADインスタンスの同期を構成し、Active Directoryフェデレーションサービス(ADFS)を介してログインを構成できました。
Azure B2Cログインポリシーを構成する
執筆時点では、サービスはプレビュー版であるため、Google +やFacebook経由でのログインなど、UIを介して最も基本的なスクリプトのみを構成できます。 Active Directoryを介したログインは、Identity Experience Frameworkを介してxmlファイルをダウンロードすることにより行われます。 ログインスクリプトをデバッグするのに約8時間かかり、モバイルログインをリファクタリングしてマイクロソフトの認証プロバイダーを固定するのにもう1日かかりました。
バックエンドでは、新しいIdentityProviderとAudienceを示すことだけが必要でした。
エントランスを設定するには、 リポジトリをダウンロードし、記事に記載されているセットアップ手順を実行する必要があります 。 ほんの数時間でxmlでプログラミングします-そして出来上がりです! クライアントはAzureサーバーを介して認証します。
見て怖がる <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <TrustFrameworkPolicy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.microsoft.com/online/cpim/schemas/2013/06" PolicySchemaVersion="0.3.0.0" TenantId="yourtenant.onmicrosoft.com" PolicyId="B2C_1A_TrustFrameworkBase" PublicPolicyUri="http://yourtenant.onmicrosoft.com/B2C_1A_TrustFrameworkBase"> <BuildingBlocks> <ClaimsSchema> <ClaimType Id="socialIdpUserId"> <DisplayName>Username</DisplayName> <DataType>string</DataType> <UserHelpText/> <UserInputType>TextBox</UserInputType> <Restriction> <Pattern RegularExpression="^[a-zA-Z0-9]+[a-zA-Z0-9_-]*$" HelpText="The username you provided is not valid. It must begin with an alphabet or number and can contain alphabets, numbers and the following symbols: _ -" /> </Restriction> </ClaimType> <ClaimType Id="tenantId"> <DisplayName>User's Object's Tenant ID</DisplayName> <DataType>string</DataType> <DefaultPartnerClaimTypes> <Protocol Name="OAuth2" PartnerClaimType="tid" /> <Protocol Name="OpenIdConnect" PartnerClaimType="tid" /> <Protocol Name="SAML2" PartnerClaimType="http://schemas.microsoft.com/identity/claims/tenantid" /> </DefaultPartnerClaimTypes> <UserHelpText>Tenant identifier (ID) of the user object in Azure AD.</UserHelpText> </ClaimType> <ClaimType Id="objectId"> <DisplayName>User's Object ID</DisplayName> <DataType>string</DataType> <DefaultPartnerClaimTypes> <Protocol Name="OAuth2" PartnerClaimType="oid" /> <Protocol Name="OpenIdConnect" PartnerClaimType="oid" /> <Protocol Name="SAML2" PartnerClaimType="http://schemas.microsoft.com/identity/claims/objectidentifier" /> </DefaultPartnerClaimTypes> <UserHelpText>Object identifier (ID) of the user object in Azure AD.</UserHelpText> </ClaimType> <ClaimType Id="signInName"> <DisplayName>Sign in name</DisplayName> <DataType>string</DataType> <UserHelpText/> <UserInputType>TextBox</UserInputType> </ClaimType> <ClaimType Id="signInNames.emailAddress"> <DisplayName>Email Address</DisplayName> <DataType>string</DataType> <UserHelpText>Email address to use for signing in.</UserHelpText> <UserInputType>TextBox</UserInputType> </ClaimType> <ClaimType Id="password"> <DisplayName>Password</DisplayName> <DataType>string</DataType> <UserHelpText>Enter password</UserHelpText> <UserInputType>Password</UserInputType> </ClaimType> <ClaimType Id="newPassword"> <DisplayName>New Password</DisplayName> <DataType>string</DataType> <UserHelpText>Enter new password</UserHelpText> <UserInputType>Password</UserInputType> <Restriction> <Pattern RegularExpression="^((?=.*[az])(?=.*[AZ])(?=.*\d)|(?=.*[az])(?=.*[AZ])(?=.*[^A-Za-z0-9])|(?=.*[az])(?=.*\d)(?=.*[^A-Za-z0-9])|(?=.*[AZ])(?=.*\d)(?=.*[^A-Za-z0-9]))([A-Za-z\d@#$%^&*\-_+=[\]{}|\\:',?/`~"();!]|\.(?!@)){8,16}$" HelpText="8-16 characters, containing 3 out of 4 of the following: Lowercase characters, uppercase characters, digits (0-9), and one or more of the following symbols: @ # $ % ^ & * - _ + = [ ] { } | \ : ' , ? / ` ~ " ( ) ; ." /> </Restriction> </ClaimType> <ClaimType Id="reenterPassword"> <DisplayName>Confirm New Password</DisplayName> <DataType>string</DataType> <UserHelpText>Confirm new password</UserHelpText> <UserInputType>Password</UserInputType> <Restriction> <Pattern RegularExpression="^((?=.*[az])(?=.*[AZ])(?=.*\d)|(?=.*[az])(?=.*[AZ])(?=.*[^A-Za-z0-9])|(?=.*[az])(?=.*\d)(?=.*[^A-Za-z0-9])|(?=.*[AZ])(?=.*\d)(?=.*[^A-Za-z0-9]))([A-Za-z\d@#$%^&*\-_+=[\]{}|\\:',?/`~"();!]|\.(?!@)){8,16}$" HelpText=" " /> </Restriction> </ClaimType> <ClaimType Id="passwordPolicies"> <DisplayName>Password Policies</DisplayName> <DataType>string</DataType> <UserHelpText>Password policies used by Azure AD to determine password strength, expiry etc.</UserHelpText> </ClaimType> <ClaimType Id="client_id"> <DisplayName>client_id</DisplayName> <DataType>string</DataType> <AdminHelpText>Special parameter passed to EvoSTS.</AdminHelpText> <UserHelpText>Special parameter passed to EvoSTS.</UserHelpText> </ClaimType> <ClaimType Id="resource_id"> <DisplayName>resource_id</DisplayName> <DataType>string</DataType> <AdminHelpText>Special parameter passed to EvoSTS.</AdminHelpText> <UserHelpText>Special parameter passed to EvoSTS.</UserHelpText> </ClaimType> <ClaimType Id="sub"> <DisplayName>Subject</DisplayName> <DataType>string</DataType> <DefaultPartnerClaimTypes> <Protocol Name="OpenIdConnect" PartnerClaimType="sub" /> </DefaultPartnerClaimTypes> <UserHelpText/> </ClaimType> <ClaimType Id="alternativeSecurityId"> <DisplayName>AlternativeSecurityId</DisplayName> <DataType>string</DataType> <UserHelpText/> </ClaimType> <ClaimType Id="mailNickName"> <DisplayName>MailNickName</DisplayName> <DataType>string</DataType> <UserHelpText>Your mail nick name as stored in the Azure Active Directory.</UserHelpText> </ClaimType> <ClaimType Id="identityProvider"> <DisplayName>Identity Provider</DisplayName> <DataType>string</DataType> <DefaultPartnerClaimTypes> <Protocol Name="OAuth2" PartnerClaimType="idp" /> <Protocol Name="OpenIdConnect" PartnerClaimType="idp" /> <Protocol Name="SAML2" PartnerClaimType="http://schemas.microsoft.com/identity/claims/identityprovider" /> </DefaultPartnerClaimTypes> <UserHelpText/> </ClaimType> <ClaimType Id="displayName"> <DisplayName>Display Name</DisplayName> <DataType>string</DataType> <DefaultPartnerClaimTypes> <Protocol Name="OAuth2" PartnerClaimType="unique_name" /> <Protocol Name="OpenIdConnect" PartnerClaimType="name" /> <Protocol Name="SAML2" PartnerClaimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" /> </DefaultPartnerClaimTypes> <UserHelpText>Your display name.</UserHelpText> <UserInputType>TextBox</UserInputType> </ClaimType> <ClaimType Id="strongAuthenticationPhoneNumber"> <DisplayName>Phone Number</DisplayName> <DataType>string</DataType> <Mask Type="Simple">XXX-XXX-</Mask> <UserHelpText>Your telephone number</UserHelpText> </ClaimType> <ClaimType Id="Verified.strongAuthenticationPhoneNumber"> <DisplayName>Verified Phone Number</DisplayName> <DataType>string</DataType> <DefaultPartnerClaimTypes> <Protocol Name="OpenIdConnect" PartnerClaimType="phone_number" /> </DefaultPartnerClaimTypes> <Mask Type="Simple">XXX-XXX-</Mask> <UserHelpText>Your office phone number that has been verified</UserHelpText> </ClaimType> <ClaimType Id="newPhoneNumberEntered"> <DisplayName>New Phone Number Entered</DisplayName> <DataType>boolean</DataType> </ClaimType> <ClaimType Id="userIdForMFA"> <DisplayName>UserId for MFA</DisplayName> <DataType>string</DataType> </ClaimType> <ClaimType Id="email"> <DisplayName>Email Address</DisplayName> <DataType>string</DataType> <DefaultPartnerClaimTypes> <Protocol Name="OpenIdConnect" PartnerClaimType="email" /> </DefaultPartnerClaimTypes> <UserHelpText>Email address that can be used to contact you.</UserHelpText> <UserInputType>TextBox</UserInputType> <Restriction> <Pattern RegularExpression="^[a-zA-Z0-9.!#$%&'^_`{}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" HelpText="Please enter a valid email address." /> </Restriction> </ClaimType> <ClaimType Id="otherMails"> <DisplayName>Alternate Email Addresses</DisplayName> <DataType>stringCollection</DataType> <UserHelpText>Email addresses that can be used to contact the user.</UserHelpText> </ClaimType> <ClaimType Id="userPrincipalName"> <DisplayName>UserPrincipalName</DisplayName> <DataType>string</DataType> <DefaultPartnerClaimTypes> <Protocol Name="OAuth2" PartnerClaimType="upn" /> <Protocol Name="OpenIdConnect" PartnerClaimType="upn" /> <Protocol Name="SAML2" PartnerClaimType="http://schemas.microsoft.com/identity/claims/userprincipalname" /> </DefaultPartnerClaimTypes> <UserHelpText>Your user name as stored in the Azure Active Directory.</UserHelpText> </ClaimType> <ClaimType Id="upnUserName"> <DisplayName>UPN User Name</DisplayName> <DataType>string</DataType> <UserHelpText>The user name for creating user principal name.</UserHelpText> </ClaimType> <ClaimType Id="newUser"> <DisplayName>User is new</DisplayName> <DataType>boolean</DataType> <UserHelpText/> </ClaimType> <ClaimType Id="executed-SelfAsserted-Input"> <DisplayName>Executed-SelfAsserted-Input</DisplayName> <DataType>string</DataType> <UserHelpText>A claim that specifies whether attributes were collected from the user.</UserHelpText> </ClaimType> <ClaimType Id="authenticationSource"> <DisplayName>AuthenticationSource</DisplayName> <DataType>string</DataType> <UserHelpText>Specifies whether the user was authenticated at Social IDP or local account.</UserHelpText> </ClaimType> <ClaimType Id="nca"> <DisplayName>nca</DisplayName> <DataType>string</DataType> <UserHelpText>Special parameter passed for local account authentication to login.microsoftonline.com.</UserHelpText> </ClaimType> <ClaimType Id="grant_type"> <DisplayName>grant_type</DisplayName> <DataType>string</DataType> <UserHelpText>Special parameter passed for local account authentication to login.microsoftonline.com.</UserHelpText> </ClaimType> <ClaimType Id="scope"> <DisplayName>scope</DisplayName> <DataType>string</DataType> <UserHelpText>Special parameter passed for local account authentication to login.microsoftonline.com.</UserHelpText> </ClaimType> <ClaimType Id="objectIdFromSession"> <DisplayName>objectIdFromSession</DisplayName> <DataType>boolean</DataType> <UserHelpText>Parameter provided by the default session management provider to indicate that the object id has been retrieved from an SSO session.</UserHelpText> </ClaimType> <ClaimType Id="isActiveMFASession"> <DisplayName>isActiveMFASession</DisplayName> <DataType>boolean</DataType> <UserHelpText>Parameter provided by the MFA session management to indicate that the user has an active MFA session.</UserHelpText> </ClaimType> <ClaimType Id="givenName"> <DisplayName>Given Name</DisplayName> <DataType>string</DataType> <DefaultPartnerClaimTypes> <Protocol Name="OAuth2" PartnerClaimType="given_name" /> <Protocol Name="OpenIdConnect" PartnerClaimType="given_name" /> <Protocol Name="SAML2" PartnerClaimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname" /> </DefaultPartnerClaimTypes> <UserHelpText>Your given name (also known as first name).</UserHelpText> <UserInputType>TextBox</UserInputType> </ClaimType> <ClaimType Id="surname"> <DisplayName>Surname</DisplayName> <DataType>string</DataType> <DefaultPartnerClaimTypes> <Protocol Name="OAuth2" PartnerClaimType="family_name" /> <Protocol Name="OpenIdConnect" PartnerClaimType="family_name" /> <Protocol Name="SAML2" PartnerClaimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname" /> </DefaultPartnerClaimTypes> <UserHelpText>Your surname (also known as family name or last name).</UserHelpText> <UserInputType>TextBox</UserInputType> </ClaimType> </ClaimsSchema> <ClaimsTransformations> <ClaimsTransformation Id="CreateOtherMailsFromEmail" TransformationMethod="AddItemToStringCollection"> <InputClaims> <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="item" /> <InputClaim ClaimTypeReferenceId="otherMails" TransformationClaimType="collection" /> </InputClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="otherMails" TransformationClaimType="collection" /> </OutputClaims> </ClaimsTransformation> <ClaimsTransformation Id="CreateRandomUPNUserName" TransformationMethod="CreateRandomString"> <InputParameters> <InputParameter Id="randomGeneratorType" DataType="string" Value="GUID" /> </InputParameters> <OutputClaims> <OutputClaim ClaimTypeReferenceId="upnUserName" TransformationClaimType="outputClaim" /> </OutputClaims> </ClaimsTransformation> <ClaimsTransformation Id="CreateUserPrincipalName" TransformationMethod="FormatStringClaim"> <InputClaims> <InputClaim ClaimTypeReferenceId="upnUserName" TransformationClaimType="inputClaim" /> </InputClaims> <InputParameters> <InputParameter Id="stringFormat" DataType="string" Value="cpim_{0}@{RelyingPartyTenantId}" /> </InputParameters> <OutputClaims> <OutputClaim ClaimTypeReferenceId="userPrincipalName" TransformationClaimType="outputClaim" /> </OutputClaims> </ClaimsTransformation> <ClaimsTransformation Id="CreateAlternativeSecurityId" TransformationMethod="CreateAlternativeSecurityId"> <InputClaims> <InputClaim ClaimTypeReferenceId="socialIdpUserId" TransformationClaimType="key" /> <InputClaim ClaimTypeReferenceId="identityProvider" TransformationClaimType="identityProvider" /> </InputClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="alternativeSecurityId" TransformationClaimType="alternativeSecurityId" /> </OutputClaims> </ClaimsTransformation> <ClaimsTransformation Id="CreateUserIdForMFA" TransformationMethod="FormatStringClaim"> <InputClaims> <InputClaim ClaimTypeReferenceId="objectId" TransformationClaimType="inputClaim" /> </InputClaims> <InputParameters> <InputParameter Id="stringFormat" DataType="string" Value="{0}@{RelyingPartyTenantId}" /> </InputParameters> <OutputClaims> <OutputClaim ClaimTypeReferenceId="userIdForMFA" TransformationClaimType="outputClaim" /> </OutputClaims> </ClaimsTransformation> <ClaimsTransformation Id="CreateSubjectClaimFromAlternativeSecurityId" TransformationMethod="CreateStringClaim"> <InputParameters> <InputParameter Id="value" DataType="string" Value="Not supported currently. Use oid claim." /> </InputParameters> <OutputClaims> <OutputClaim ClaimTypeReferenceId="sub" TransformationClaimType="createdClaim" /> </OutputClaims> </ClaimsTransformation> </ClaimsTransformations> <ClientDefinitions> <ClientDefinition Id="DefaultWeb"> <ClientUIFilterFlags>LineMarkers, MetaRefresh</ClientUIFilterFlags> </ClientDefinition> </ClientDefinitions> <ContentDefinitions> <ContentDefinition Id="api.error"> <LoadUri>~/tenant/default/exception.cshtml</LoadUri> <RecoveryUri>~/common/default_page_error.html</RecoveryUri> <DataUri>urn:com:microsoft:aad:b2c:elements:globalexception:1.1.0</DataUri> <Metadata> <Item Key="DisplayName">Error page</Item> </Metadata> </ContentDefinition> <ContentDefinition Id="api.idpselections"> <LoadUri>~/tenant/default/idpSelector.cshtml</LoadUri> <RecoveryUri>~/common/default_page_error.html</RecoveryUri> <DataUri>urn:com:microsoft:aad:b2c:elements:idpselection:1.0.0</DataUri> <Metadata> <Item Key="DisplayName">Idp selection page</Item> <Item Key="language.intro">Sign in</Item> </Metadata> </ContentDefinition> <ContentDefinition Id="api.idpselections.signup"> <LoadUri>~/tenant/default/idpSelector.cshtml</LoadUri> <RecoveryUri>~/common/default_page_error.html</RecoveryUri> <DataUri>urn:com:microsoft:aad:b2c:elements:idpselection:1.0.0</DataUri> <Metadata> <Item Key="DisplayName">Idp selection page</Item> <Item Key="language.intro">Sign up</Item> </Metadata> </ContentDefinition> <ContentDefinition Id="api.signuporsignin"> <LoadUri>~/tenant/default/unified.cshtml</LoadUri> <RecoveryUri>~/common/default_page_error.html</RecoveryUri> <DataUri>urn:com:microsoft:aad:b2c:elements:unifiedssp:1.0.0</DataUri> <Metadata> <Item Key="DisplayName">Signin and Signup</Item> </Metadata> </ContentDefinition> <ContentDefinition Id="api.phonefactor"> <LoadUri>~/tenant/default/multifactor-1.0.0.cshtml</LoadUri> <RecoveryUri>~/common/default_page_error.html</RecoveryUri> <DataUri>urn:com:microsoft:aad:b2c:elements:multifactor:1.1.0</DataUri> <Metadata> <Item Key="DisplayName">Multi-factor authentication page</Item> </Metadata> </ContentDefinition> <ContentDefinition Id="api.selfasserted"> <LoadUri>~/tenant/default/selfAsserted.cshtml</LoadUri> <RecoveryUri>~/common/default_page_error.html</RecoveryUri> <DataUri>urn:com:microsoft:aad:b2c:elements:selfasserted:1.1.0</DataUri> <Metadata> <Item Key="DisplayName">Collect information from user page</Item> </Metadata> </ContentDefinition> <ContentDefinition Id="api.selfasserted.profileupdate"> <LoadUri>~/tenant/default/updateProfile.cshtml</LoadUri> <RecoveryUri>~/common/default_page_error.html</RecoveryUri> <DataUri>urn:com:microsoft:aad:b2c:elements:selfasserted:1.1.0</DataUri> <Metadata> <Item Key="DisplayName">Collect information from user page</Item> </Metadata> </ContentDefinition> <ContentDefinition Id="api.localaccountsignup"> <LoadUri>~/tenant/default/selfAsserted.cshtml</LoadUri> <RecoveryUri>~/common/default_page_error.html</RecoveryUri> <DataUri>urn:com:microsoft:aad:b2c:elements:selfasserted:1.1.0</DataUri> <Metadata> <Item Key="DisplayName">Local account sign up page</Item> </Metadata> </ContentDefinition> <ContentDefinition Id="api.localaccountpasswordreset"> <LoadUri>~/tenant/default/selfAsserted.cshtml</LoadUri> <RecoveryUri>~/common/default_page_error.html</RecoveryUri> <DataUri>urn:com:microsoft:aad:b2c:elements:selfasserted:1.1.0</DataUri> <Metadata> <Item Key="DisplayName">Local account change password page</Item> </Metadata> </ContentDefinition> </ContentDefinitions> </BuildingBlocks> <ClaimsProviders> <ClaimsProvider> <Domain>facebook.com</Domain> <DisplayName>Facebook</DisplayName> <TechnicalProfiles> <TechnicalProfile Id="Facebook-OAUTH"> <DisplayName>Facebook</DisplayName> <Protocol Name="OAuth2" /> <Metadata> <Item Key="ProviderName">facebook</Item> <Item Key="authorization_endpoint">https://www.facebook.com/dialog/oauth</Item> <Item Key="AccessTokenEndpoint">https://graph.facebook.com/oauth/access_token</Item> <Item Key="HttpBinding">GET</Item> <Item Key="UsePolicyInRedirectUri">0</Item> <Item Key="AccessTokenResponseFormat">json</Item> </Metadata> <CryptographicKeys> <Key Id="client_secret" StorageReferenceId="B2C_1A_FacebookSecret" /> </CryptographicKeys> <InputClaims /> <OutputClaims> <OutputClaim ClaimTypeReferenceId="socialIdpUserId" PartnerClaimType="id" /> <OutputClaim ClaimTypeReferenceId="givenName" PartnerClaimType="first_name" /> <OutputClaim ClaimTypeReferenceId="surname" PartnerClaimType="last_name" /> <OutputClaim ClaimTypeReferenceId="displayName" PartnerClaimType="name" /> <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="email" /> <OutputClaim ClaimTypeReferenceId="identityProvider" DefaultValue="facebook.com" /> <OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="socialIdpAuthentication" /> </OutputClaims> <OutputClaimsTransformations> <OutputClaimsTransformation ReferenceId="CreateRandomUPNUserName" /> <OutputClaimsTransformation ReferenceId="CreateUserPrincipalName" /> <OutputClaimsTransformation ReferenceId="CreateAlternativeSecurityId" /> </OutputClaimsTransformations> <UseTechnicalProfileForSessionManagement ReferenceId="SM-SocialLogin" /> </TechnicalProfile> </TechnicalProfiles> </ClaimsProvider> <ClaimsProvider> <DisplayName>Local Account SignIn</DisplayName> <TechnicalProfiles> <TechnicalProfile Id="login-NonInteractive"> <DisplayName>Local Account SignIn</DisplayName> <Protocol Name="OpenIdConnect" /> <Metadata> <Item Key="UserMessageIfClaimsPrincipalDoesNotExist">We can't seem to find your account</Item> <Item Key="UserMessageIfInvalidPassword">Your password is incorrect</Item> <Item Key="UserMessageIfOldPasswordUsed">Looks like you used an old password</Item> <Item Key="ProviderName">https://sts.windows.net/</Item> <Item Key="METADATA">https://login.microsoftonline.com/{tenant}/.well-known/openid-configuration</Item> <Item Key="authorization_endpoint">https://login.microsoftonline.com/{tenant}/oauth2/token</Item> <Item Key="response_types">id_token</Item> <Item Key="response_mode">query</Item> <Item Key="scope">email openid</Item> <Item Key="UsePolicyInRedirectUri">false</Item> <Item Key="HttpBinding">POST</Item> </Metadata> <InputClaims> <InputClaim ClaimTypeReferenceId="signInName" PartnerClaimType="username" Required="true" /> <InputClaim ClaimTypeReferenceId="password" Required="true" /> <InputClaim ClaimTypeReferenceId="grant_type" DefaultValue="password" /> <InputClaim ClaimTypeReferenceId="scope" DefaultValue="openid" /> <InputClaim ClaimTypeReferenceId="nca" PartnerClaimType="nca" DefaultValue="1" /> </InputClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="oid" /> <OutputClaim ClaimTypeReferenceId="tenantId" PartnerClaimType="tid" /> <OutputClaim ClaimTypeReferenceId="givenName" PartnerClaimType="given_name" /> <OutputClaim ClaimTypeReferenceId="surName" PartnerClaimType="family_name" /> <OutputClaim ClaimTypeReferenceId="displayName" PartnerClaimType="name" /> <OutputClaim ClaimTypeReferenceId="userPrincipalName" PartnerClaimType="upn" /> <OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="localAccountAuthentication" /> </OutputClaims> </TechnicalProfile> </TechnicalProfiles> </ClaimsProvider> <ClaimsProvider> <DisplayName>PhoneFactor</DisplayName> <TechnicalProfiles> <TechnicalProfile Id="PhoneFactor-InputOrVerify"> <DisplayName>PhoneFactor</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.PhoneFactorProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <Metadata> <Item Key="ContentDefinitionReferenceId">api.phonefactor</Item> <Item Key="ManualPhoneNumberEntryAllowed">true</Item> </Metadata> <CryptographicKeys> <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" /> </CryptographicKeys> <InputClaimsTransformations> <InputClaimsTransformation ReferenceId="CreateUserIdForMFA" /> </InputClaimsTransformations> <InputClaims> <InputClaim ClaimTypeReferenceId="userIdForMFA" PartnerClaimType="UserId" /> <InputClaim ClaimTypeReferenceId="strongAuthenticationPhoneNumber" /> </InputClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="Verified.strongAuthenticationPhoneNumber" PartnerClaimType="Verified.OfficePhone" /> <OutputClaim ClaimTypeReferenceId="newPhoneNumberEntered" PartnerClaimType="newPhoneNumberEntered" /> </OutputClaims> <UseTechnicalProfileForSessionManagement ReferenceId="SM-MFA" /> </TechnicalProfile> </TechnicalProfiles> </ClaimsProvider> <ClaimsProvider> <DisplayName>Azure Active Directory</DisplayName> <TechnicalProfiles> <TechnicalProfile Id="AAD-Common"> <DisplayName>Azure Active Directory</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.AzureActiveDirectoryProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <CryptographicKeys> <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" /> </CryptographicKeys> <IncludeInSso>false</IncludeInSso> <UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" /> </TechnicalProfile> <TechnicalProfile Id="AAD-UserWriteUsingAlternativeSecurityId"> <Metadata> <Item Key="Operation">Write</Item> <Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">true</Item> <Item Key="UserMessageIfClaimsPrincipalAlreadyExists">You are already registered, please press the back button and sign in instead.</Item> </Metadata> <IncludeInSso>false</IncludeInSso> <InputClaimsTransformations> <InputClaimsTransformation ReferenceId="CreateOtherMailsFromEmail" /> </InputClaimsTransformations> <InputClaims> <InputClaim ClaimTypeReferenceId="AlternativeSecurityId" PartnerClaimType="alternativeSecurityId" Required="true" /> </InputClaims> <PersistedClaims> <PersistedClaim ClaimTypeReferenceId="alternativeSecurityId" /> <PersistedClaim ClaimTypeReferenceId="userPrincipalName" /> <PersistedClaim ClaimTypeReferenceId="mailNickName" DefaultValue="unknown" /> <PersistedClaim ClaimTypeReferenceId="displayName" DefaultValue="unknown" /> <PersistedClaim ClaimTypeReferenceId="otherMails" /> <PersistedClaim ClaimTypeReferenceId="givenName" /> <PersistedClaim ClaimTypeReferenceId="surname" /> </PersistedClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="objectId" /> <OutputClaim ClaimTypeReferenceId="newUser" PartnerClaimType="newClaimsPrincipalCreated" /> <OutputClaim ClaimTypeReferenceId="otherMails" /> </OutputClaims> <IncludeTechnicalProfile ReferenceId="AAD-Common" /> <UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" /> </TechnicalProfile> <TechnicalProfile Id="AAD-UserReadUsingAlternativeSecurityId"> <Metadata> <Item Key="Operation">Read</Item> <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item> <Item Key="UserMessageIfClaimsPrincipalDoesNotExist">User does not exist. Please sign up before you can sign in.</Item> </Metadata> <InputClaims> <InputClaim ClaimTypeReferenceId="AlternativeSecurityId" PartnerClaimType="alternativeSecurityId" Required="true" /> </InputClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="objectId" /> <OutputClaim ClaimTypeReferenceId="userPrincipalName" /> <OutputClaim ClaimTypeReferenceId="displayName" /> <OutputClaim ClaimTypeReferenceId="otherMails" /> <OutputClaim ClaimTypeReferenceId="givenName" /> <OutputClaim ClaimTypeReferenceId="surname" /> </OutputClaims> <IncludeTechnicalProfile ReferenceId="AAD-Common" /> </TechnicalProfile> <TechnicalProfile Id="AAD-UserReadUsingAlternativeSecurityId-NoError"> <Metadata> <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">false</Item> </Metadata> <IncludeTechnicalProfile ReferenceId="AAD-UserReadUsingAlternativeSecurityId" /> </TechnicalProfile> <TechnicalProfile Id="AAD-UserWriteUsingLogonEmail"> <Metadata> <Item Key="Operation">Write</Item> <Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">true</Item> </Metadata> <IncludeInSso>false</IncludeInSso> <InputClaims> <InputClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames.emailAddress" Required="true" /> </InputClaims> <PersistedClaims> <PersistedClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames.emailAddress" /> <PersistedClaim ClaimTypeReferenceId="newPassword" PartnerClaimType="password"/> <PersistedClaim ClaimTypeReferenceId="displayName" DefaultValue="unknown" /> <PersistedClaim ClaimTypeReferenceId="passwordPolicies" DefaultValue="DisablePasswordExpiration" /> <PersistedClaim ClaimTypeReferenceId="Verified.strongAuthenticationPhoneNumber" PartnerClaimType="strongAuthenticationPhoneNumber" /> <PersistedClaim ClaimTypeReferenceId="givenName" /> <PersistedClaim ClaimTypeReferenceId="surname" /> </PersistedClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="objectId" /> <OutputClaim ClaimTypeReferenceId="newUser" PartnerClaimType="newClaimsPrincipalCreated" /> <OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="localAccountAuthentication" /> <OutputClaim ClaimTypeReferenceId="userPrincipalName" /> <OutputClaim ClaimTypeReferenceId="signInNames.emailAddress" /> </OutputClaims> <IncludeTechnicalProfile ReferenceId="AAD-Common" /> <UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" /> </TechnicalProfile> <TechnicalProfile Id="AAD-UserReadUsingEmailAddress"> <Metadata> <Item Key="Operation">Read</Item> <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item> <Item Key="UserMessageIfClaimsPrincipalDoesNotExist">An account could not be found for the provided user ID.</Item> </Metadata> <IncludeInSso>false</IncludeInSso> <InputClaims> <InputClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames" Required="true" /> </InputClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="objectId" /> <OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="localAccountAuthentication" /> <OutputClaim ClaimTypeReferenceId="strongAuthenticationPhoneNumber" /> <OutputClaim ClaimTypeReferenceId="userPrincipalName" /> <OutputClaim ClaimTypeReferenceId="displayName" /> <OutputClaim ClaimTypeReferenceId="otherMails" /> <OutputClaim ClaimTypeReferenceId="signInNames.emailAddress" /> </OutputClaims> <IncludeTechnicalProfile ReferenceId="AAD-Common" /> </TechnicalProfile> <TechnicalProfile Id="AAD-UserWritePasswordUsingObjectId"> <Metadata> <Item Key="Operation">Write</Item> <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item> </Metadata> <IncludeInSso>false</IncludeInSso> <InputClaims> <InputClaim ClaimTypeReferenceId="objectId" Required="true" /> </InputClaims> <PersistedClaims> <PersistedClaim ClaimTypeReferenceId="objectId" /> <PersistedClaim ClaimTypeReferenceId="newPassword" PartnerClaimType="password"/> <PersistedClaim ClaimTypeReferenceId="Verified.strongAuthenticationPhoneNumber" PartnerClaimType="strongAuthenticationPhoneNumber" /> </PersistedClaims> <IncludeTechnicalProfile ReferenceId="AAD-Common" /> </TechnicalProfile> <TechnicalProfile Id="AAD-UserWriteProfileUsingObjectId"> <Metadata> <Item Key="Operation">Write</Item> <Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">false</Item> <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item> </Metadata> <IncludeInSso>false</IncludeInSso> <InputClaims> <InputClaim ClaimTypeReferenceId="objectId" Required="true" /> </InputClaims> <PersistedClaims> <PersistedClaim ClaimTypeReferenceId="objectId" /> <PersistedClaim ClaimTypeReferenceId="Verified.strongAuthenticationPhoneNumber" PartnerClaimType="strongAuthenticationPhoneNumber" /> <PersistedClaim ClaimTypeReferenceId="givenName" /> <PersistedClaim ClaimTypeReferenceId="surname" /> </PersistedClaims> <IncludeTechnicalProfile ReferenceId="AAD-Common" /> </TechnicalProfile> <TechnicalProfile Id="AAD-UserReadUsingObjectId"> <Metadata> <Item Key="Operation">Read</Item> <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item> </Metadata> <IncludeInSso>false</IncludeInSso> <InputClaims> <InputClaim ClaimTypeReferenceId="objectId" Required="true" /> </InputClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="strongAuthenticationPhoneNumber" /> <OutputClaim ClaimTypeReferenceId="signInNames.emailAddress" /> <OutputClaim ClaimTypeReferenceId="displayName" /> <OutputClaim ClaimTypeReferenceId="otherMails" /> <OutputClaim ClaimTypeReferenceId="givenName" /> <OutputClaim ClaimTypeReferenceId="surname" /> </OutputClaims> <IncludeTechnicalProfile ReferenceId="AAD-Common" /> </TechnicalProfile> <TechnicalProfile Id="AAD-UserWritePhoneNumberUsingObjectId"> <Metadata> <Item Key="Operation">Write</Item> <Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">false</Item> <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item> </Metadata> <IncludeInSso>false</IncludeInSso> <InputClaims> <InputClaim ClaimTypeReferenceId="objectId" Required="true" /> </InputClaims> <PersistedClaims> <PersistedClaim ClaimTypeReferenceId="objectId" /> <PersistedClaim ClaimTypeReferenceId="Verified.strongAuthenticationPhoneNumber" PartnerClaimType="strongAuthenticationPhoneNumber" /> </PersistedClaims> <IncludeTechnicalProfile ReferenceId="AAD-Common" /> </TechnicalProfile> </TechnicalProfiles> </ClaimsProvider> <ClaimsProvider> <DisplayName>Self Asserted</DisplayName> <TechnicalProfiles> <TechnicalProfile Id="SelfAsserted-Social"> <DisplayName>User ID signup</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <Metadata> <Item Key="ContentDefinitionReferenceId">api.selfasserted</Item> </Metadata> <CryptographicKeys> <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" /> </CryptographicKeys> <InputClaims> <InputClaim ClaimTypeReferenceId="displayName" /> <InputClaim ClaimTypeReferenceId="givenName" /> <InputClaim ClaimTypeReferenceId="surname" /> </InputClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="objectId" /> <OutputClaim ClaimTypeReferenceId="newUser" /> <OutputClaim ClaimTypeReferenceId="executed-SelfAsserted-Input" DefaultValue="true" /> <OutputClaim ClaimTypeReferenceId="displayName" /> <OutputClaim ClaimTypeReferenceId="givenName" /> <OutputClaim ClaimTypeReferenceId="surname" /> </OutputClaims> <ValidationTechnicalProfiles> <ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingAlternativeSecurityId" /> </ValidationTechnicalProfiles> <UseTechnicalProfileForSessionManagement ReferenceId="SM-SocialSignup" /> </TechnicalProfile> <TechnicalProfile Id="SelfAsserted-ProfileUpdate"> <DisplayName>User ID signup</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <Metadata> <Item Key="ContentDefinitionReferenceId">api.selfasserted.profileupdate</Item> </Metadata> <IncludeInSso>false</IncludeInSso> <InputClaims> <InputClaim ClaimTypeReferenceId="alternativeSecurityId" /> <InputClaim ClaimTypeReferenceId="userPrincipalName" /> <InputClaim ClaimTypeReferenceId="givenName" /> <InputClaim ClaimTypeReferenceId="surname" /> </InputClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="executed-SelfAsserted-Input" DefaultValue="true" /> <OutputClaim ClaimTypeReferenceId="givenName" /> <OutputClaim ClaimTypeReferenceId="surname" /> </OutputClaims> <ValidationTechnicalProfiles> <ValidationTechnicalProfile ReferenceId="AAD-UserWriteProfileUsingObjectId" /> </ValidationTechnicalProfiles> </TechnicalProfile> </TechnicalProfiles> </ClaimsProvider> <ClaimsProvider> <DisplayName>Local Account</DisplayName> <TechnicalProfiles> <TechnicalProfile Id="LocalAccountSignUpWithLogonEmail"> <DisplayName>Email signup</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <Metadata> <Item Key="IpAddressClaimReferenceId">IpAddress</Item> <Item Key="ContentDefinitionReferenceId">api.localaccountsignup</Item> <Item Key="language.button_continue">Create</Item> </Metadata> <CryptographicKeys> <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" /> </CryptographicKeys> <InputClaims> <InputClaim ClaimTypeReferenceId="email" /> </InputClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="objectId" /> <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true" /> <OutputClaim ClaimTypeReferenceId="newPassword" Required="true" /> <OutputClaim ClaimTypeReferenceId="reenterPassword" Required="true" /> <OutputClaim ClaimTypeReferenceId="executed-SelfAsserted-Input" DefaultValue="true" /> <OutputClaim ClaimTypeReferenceId="authenticationSource" /> <OutputClaim ClaimTypeReferenceId="newUser" /> <OutputClaim ClaimTypeReferenceId="displayName" /> <OutputClaim ClaimTypeReferenceId="givenName" /> <OutputClaim ClaimTypeReferenceId="surName" /> </OutputClaims> <ValidationTechnicalProfiles> <ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingLogonEmail" /> </ValidationTechnicalProfiles> <UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" /> </TechnicalProfile> <TechnicalProfile Id="SelfAsserted-LocalAccountSignin-Email"> <DisplayName>Local Account Signin</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <Metadata> <Item Key="SignUpTarget">SignUpWithLogonEmailExchange</Item> <Item Key="setting.operatingMode">Email</Item> <Item Key="ContentDefinitionReferenceId">api.selfasserted</Item> </Metadata> <IncludeInSso>false</IncludeInSso> <InputClaims> <InputClaim ClaimTypeReferenceId="signInName" /> </InputClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="signInName" Required="true" /> <OutputClaim ClaimTypeReferenceId="password" Required="true" /> <OutputClaim ClaimTypeReferenceId="objectId" /> <OutputClaim ClaimTypeReferenceId="authenticationSource" /> </OutputClaims> <ValidationTechnicalProfiles> <ValidationTechnicalProfile ReferenceId="login-NonInteractive" /> </ValidationTechnicalProfiles> <UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" /> </TechnicalProfile> <TechnicalProfile Id="LocalAccountDiscoveryUsingEmailAddress"> <DisplayName>Reset password using email address</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <Metadata> <Item Key="IpAddressClaimReferenceId">IpAddress</Item> <Item Key="ContentDefinitionReferenceId">api.localaccountpasswordreset</Item> </Metadata> <CryptographicKeys> <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" /> </CryptographicKeys> <IncludeInSso>false</IncludeInSso> <OutputClaims> <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true" /> <OutputClaim ClaimTypeReferenceId="objectId" /> <OutputClaim ClaimTypeReferenceId="userPrincipalName" /> <OutputClaim ClaimTypeReferenceId="authenticationSource" /> <OutputClaim ClaimTypeReferenceId="strongAuthenticationPhoneNumber" /> </OutputClaims> <ValidationTechnicalProfiles> <ValidationTechnicalProfile ReferenceId="AAD-UserReadUsingEmailAddress" /> </ValidationTechnicalProfiles> </TechnicalProfile> <TechnicalProfile Id="LocalAccountWritePasswordUsingObjectId"> <DisplayName>Change password (username)</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <Metadata> <Item Key="ContentDefinitionReferenceId">api.localaccountpasswordreset</Item> </Metadata> <CryptographicKeys> <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" /> </CryptographicKeys> <InputClaims> <InputClaim ClaimTypeReferenceId="objectId" /> <InputClaim ClaimTypeReferenceId="Verified.strongAuthenticationPhoneNumber" /> </InputClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="newPassword" Required="true" /> <OutputClaim ClaimTypeReferenceId="reenterPassword" Required="true" /> </OutputClaims> <ValidationTechnicalProfiles> <ValidationTechnicalProfile ReferenceId="AAD-UserWritePasswordUsingObjectId" /> </ValidationTechnicalProfiles> </TechnicalProfile> </TechnicalProfiles> </ClaimsProvider> <ClaimsProvider> <DisplayName>Session Management</DisplayName> <TechnicalProfiles> <TechnicalProfile Id="SM-Noop"> <DisplayName>Noop Session Management Provider</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.SSO.NoopSSOSessionProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> </TechnicalProfile> <TechnicalProfile Id="SM-AAD"> <DisplayName>Session Mananagement Provider</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.SSO.DefaultSSOSessionProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <PersistedClaims> <PersistedClaim ClaimTypeReferenceId="objectId" /> <PersistedClaim ClaimTypeReferenceId="signInName" /> <PersistedClaim ClaimTypeReferenceId="authenticationSource" /> <PersistedClaim ClaimTypeReferenceId="identityProvider" /> <PersistedClaim ClaimTypeReferenceId="newUser" /> <PersistedClaim ClaimTypeReferenceId="executed-SelfAsserted-Input" /> </PersistedClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="objectIdFromSession" DefaultValue="true"/> </OutputClaims> </TechnicalProfile> <TechnicalProfile Id="SM-SocialSignup"> <IncludeTechnicalProfile ReferenceId="SM-AAD" /> </TechnicalProfile> <TechnicalProfile Id="SM-SocialLogin"> <DisplayName>Session Mananagement Provider</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.SSO.ExternalLoginSSOSessionProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <Metadata> <Item Key="AlwaysFetchClaimsFromProvider">true</Item> </Metadata> <PersistedClaims> <PersistedClaim ClaimTypeReferenceId="AlternativeSecurityId" /> </PersistedClaims> </TechnicalProfile> <TechnicalProfile Id="SM-MFA"> <DisplayName>Session Mananagement Provider</DisplayName> <Protocol Name="Proprietary" Handler="Web.TPEngine.SSO.DefaultSSOSessionProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <PersistedClaims> <PersistedClaim ClaimTypeReferenceId="strongAuthenticationPhoneNumber" /> </PersistedClaims> <OutputClaims> <OutputClaim ClaimTypeReferenceId="isActiveMFASession" DefaultValue="true"/> </OutputClaims> </TechnicalProfile> </TechnicalProfiles> </ClaimsProvider> <ClaimsProvider> <DisplayName>Trustframework Policy Engine TechnicalProfiles</DisplayName> <TechnicalProfiles> <TechnicalProfile Id="TpEngine_c3bd4fe2-1775-4013-b91d-35f16d377d13"> <DisplayName>Trustframework Policy Engine Default Technical Profile</DisplayName> <Protocol Name="None" /> <Metadata> <Item Key="url">{service:te}</Item> </Metadata> </TechnicalProfile> </TechnicalProfiles> </ClaimsProvider> <ClaimsProvider> <DisplayName>Token Issuer</DisplayName> <TechnicalProfiles> <TechnicalProfile Id="JwtIssuer"> <DisplayName>JWT Issuer</DisplayName> <Protocol Name="None" /> <OutputTokenFormat>JWT</OutputTokenFormat> <Metadata> <Item Key="client_id">{service:te}</Item> <Item Key="issuer_refresh_token_user_identity_claim_type">objectId</Item> <Item Key="SendTokenResponseBodyWithJsonNumbers">true</Item> </Metadata> <CryptographicKeys> <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" /> <Key Id="issuer_refresh_token_key" StorageReferenceId="B2C_1A_TokenEncryptionKeyContainer" /> </CryptographicKeys> <InputClaims /> <OutputClaims /> </TechnicalProfile> </TechnicalProfiles> </ClaimsProvider> </ClaimsProviders> <UserJourneys> <UserJourney Id="SignUpOrSignIn"> <OrchestrationSteps> <OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signuporsignin"> <ClaimsProviderSelections> <ClaimsProviderSelection TargetClaimsExchangeId="FacebookExchange" /> <ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" /> </ClaimsProviderSelections> <ClaimsExchanges> <ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="2" Type="ClaimsExchange"> <Preconditions> <Precondition Type="ClaimsExist" ExecuteActionsIf="true"> <Value>objectId</Value> <Action>SkipThisOrchestrationStep</Action> </Precondition> </Preconditions> <ClaimsExchanges> <ClaimsExchange Id="FacebookExchange" TechnicalProfileReferenceId="Facebook-OAUTH" /> <ClaimsExchange Id="SignUpWithLogonEmailExchange" TechnicalProfileReferenceId="LocalAccountSignUpWithLogonEmail" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="3" Type="ClaimsExchange"> <Preconditions> <Precondition Type="ClaimEquals" ExecuteActionsIf="true"> <Value>authenticationSource</Value> <Value>localAccountAuthentication</Value> <Action>SkipThisOrchestrationStep</Action> </Precondition> </Preconditions> <ClaimsExchanges> <ClaimsExchange Id="AADUserReadUsingAlternativeSecurityId" TechnicalProfileReferenceId="AAD-UserReadUsingAlternativeSecurityId-NoError" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="4" Type="ClaimsExchange"> <Preconditions> <Precondition Type="ClaimsExist" ExecuteActionsIf="true"> <Value>objectId</Value> <Action>SkipThisOrchestrationStep</Action> </Precondition> </Preconditions> <ClaimsExchanges> <ClaimsExchange Id="SelfAsserted-Social" TechnicalProfileReferenceId="SelfAsserted-Social" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="5" Type="ClaimsExchange"> <Preconditions> <Precondition Type="ClaimEquals" ExecuteActionsIf="true"> <Value>authenticationSource</Value> <Value>socialIdpAuthentication</Value> <Action>SkipThisOrchestrationStep</Action> </Precondition> </Preconditions> <ClaimsExchanges> <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="6" Type="ClaimsExchange"> <Preconditions> <Precondition Type="ClaimsExist" ExecuteActionsIf="true"> <Value>objectId</Value> <Action>SkipThisOrchestrationStep</Action> </Precondition> </Preconditions> <ClaimsExchanges> <ClaimsExchange Id="AADUserWrite" TechnicalProfileReferenceId="AAD-UserWriteUsingAlternativeSecurityId" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="7" Type="ClaimsExchange"> <Preconditions> <Precondition Type="ClaimsExist" ExecuteActionsIf="true"> <Value>isActiveMFASession</Value> <Action>SkipThisOrchestrationStep</Action> </Precondition> </Preconditions> <ClaimsExchanges> <ClaimsExchange Id="PhoneFactor-Verify" TechnicalProfileReferenceId="PhoneFactor-InputOrVerify" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="8" Type="ClaimsExchange"> <Preconditions> <Precondition Type="ClaimsExist" ExecuteActionsIf="false"> <Value>newPhoneNumberEntered</Value> <Action>SkipThisOrchestrationStep</Action> </Precondition> </Preconditions> <ClaimsExchanges> <ClaimsExchange Id="AADUserWriteWithObjectId" TechnicalProfileReferenceId="AAD-UserWritePhoneNumberUsingObjectId" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="9" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" /> </OrchestrationSteps> <ClientDefinition ReferenceId="DefaultWeb" /> </UserJourney> <UserJourney Id="ProfileEdit"> <OrchestrationSteps> <OrchestrationStep Order="1" Type="ClaimsProviderSelection" ContentDefinitionReferenceId="api.idpselections"> <ClaimsProviderSelections> <ClaimsProviderSelection TargetClaimsExchangeId="FacebookExchange" /> <ClaimsProviderSelection TargetClaimsExchangeId="LocalAccountSigninEmailExchange" /> </ClaimsProviderSelections> </OrchestrationStep> <OrchestrationStep Order="2" Type="ClaimsExchange"> <ClaimsExchanges> <ClaimsExchange Id="FacebookExchange" TechnicalProfileReferenceId="Facebook-OAUTH" /> <ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="3" Type="ClaimsExchange"> <Preconditions> <Precondition Type="ClaimEquals" ExecuteActionsIf="true"> <Value>authenticationSource</Value> <Value>localAccountAuthentication</Value> <Action>SkipThisOrchestrationStep</Action> </Precondition> </Preconditions> <ClaimsExchanges> <ClaimsExchange Id="AADUserRead" TechnicalProfileReferenceId="AAD-UserReadUsingAlternativeSecurityId" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="4" Type="ClaimsExchange"> <Preconditions> <Precondition Type="ClaimEquals" ExecuteActionsIf="true"> <Value>authenticationSource</Value> <Value>socialIdpAuthentication</Value> <Action>SkipThisOrchestrationStep</Action> </Precondition> </Preconditions> <ClaimsExchanges> <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="5" Type="ClaimsExchange"> <ClaimsExchanges> <ClaimsExchange Id="PhoneFactor" TechnicalProfileReferenceId="PhoneFactor-InputOrVerify" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="6" Type="ClaimsExchange"> <ClaimsExchanges> <ClaimsExchange Id="B2CUserProfileUpdateExchange" TechnicalProfileReferenceId="SelfAsserted-ProfileUpdate" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="7" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" /> </OrchestrationSteps> <ClientDefinition ReferenceId="DefaultWeb" /> </UserJourney> <UserJourney Id="PasswordReset"> <OrchestrationSteps> <OrchestrationStep Order="1" Type="ClaimsExchange"> <ClaimsExchanges> <ClaimsExchange Id="PasswordResetUsingEmailAddressExchange" TechnicalProfileReferenceId="LocalAccountDiscoveryUsingEmailAddress" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="2" Type="ClaimsExchange"> <ClaimsExchanges> <ClaimsExchange Id="PhoneFactor-Verify" TechnicalProfileReferenceId="PhoneFactor-InputOrVerify" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="3" Type="ClaimsExchange"> <ClaimsExchanges> <ClaimsExchange Id="NewCredentials" TechnicalProfileReferenceId="LocalAccountWritePasswordUsingObjectId" /> </ClaimsExchanges> </OrchestrationStep> <OrchestrationStep Order="4" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" /> </OrchestrationSteps> <ClientDefinition ReferenceId="DefaultWeb" /> </UserJourney> </UserJourneys> </TrustFrameworkPolicy>
. , , ( , ).
Azure Active Directory B2C ADFS :
Active Directory public class AuthImpl { private static final String TAG = AuthImpl.class.getSimpleName(); private Activity activity; private PublicClientApplication authClient; private AuthTokenProvider authTokenProvider; private String[] scopes; @Inject AuthImpl(AppCompatActivity activity, PublicClientApplication authClient, AuthTokenProvider authTokenProvider) { this.activity = activity; this.authClient = authClient; this.authTokenProvider = authTokenProvider; this.scopes = Constants.SCOPES.split("\\s+"); } public boolean isUserAuthenticated() { return AndroidHelpers.isEmulator() || getCurrentUser() != null; } private User getCurrentUser() { try { return Helpers.getUserByPolicy(authClient.getUsers(), Constants.SISU_POLICY); } catch (MsalClientException e) { Log.d(TAG, "MSAL Exception Generated while getting users: " + e.toString()); } catch (IndexOutOfBoundsException e) { Log.d(TAG, "User at this position does not exist: " + e.toString()); } return null; } public Single<AuthResultDto> login() { return Single.create(emitter -> { try { User currentUser = Helpers.getUserByPolicy(authClient.getUsers(), Constants.SISU_POLICY); if (currentUser != null) { authClient.acquireTokenSilentAsync( scopes, currentUser, String.format(Constants.AUTHORITY, Constants.TENANT, Constants.SISU_POLICY), false, getAuthSilentCallback(emitter)); } else { authClient.acquireToken(activity, scopes, getAuthInteractiveCallback(emitter)); } } catch (MsalClientException e) { Log.d(TAG, "MSAL Exception Generated while getting users: " + e.toString()); } catch (IndexOutOfBoundsException e) { Log.d(TAG, "User at this position does not exist: " + e.toString()); } }); }
. , :
- , Google Chrome.
- Azure AD .
- ADFS . Chrome .
Google Firebase Auth
, , , . Google Firebase Auth, .
, Google Firebase Auth .
Google, Firebase .
Firebase private final FirebaseAuth authInstance; private CompositeDisposable disposables; private EventSubscriber eventSubscriber; public Single<AuthResultDto> login(boolean forceRefreshToken) { if (disposables != null) { disposables.dispose(); } disposables = new CompositeDisposable(); return Single.create(emitter -> { FirebaseUser user = authInstance.getCurrentUser(); if (user == null || !user.isEmailVerified()) { List<AuthUI.IdpConfig> providers = Arrays.asList( new AuthUI.IdpConfig.EmailBuilder().setRequireName(true).build(), new AuthUI.IdpConfig.GoogleBuilder().build()); activity.startActivityForResult( AuthUI.getInstance() .createSignInIntentBuilder() .setAvailableProviders(providers) .build(), MainActivity.REQUES_LOGIN); } else { if (forceRefreshToken) { refreshToken(); } else { emitter.onSuccess(new AuthResultDto(false)); } } disposables.add(this.eventSubscriber.getEvent(new AuthResultDto(true)) .subscribe(e -> { emitter.onSuccess(e); disposables.dispose(); })); }); } private void refreshToken() { FirebaseUser user = authInstance.getCurrentUser(); user.getIdToken(true) .addOnCompleteListener(task -> { if (task.isSuccessful()) { GetTokenResult tokenResult = task.getResult(); String idToken = tokenResult.getToken();
, Firebase, Azure AD . Azure.
, , .
Auth0 — , . API, . - , :)
Azure Active Directory B2C — Enterprise. , . , xml. — B2C , . , .
Firebase Auth — . , . — - .
?
, OpenId Connect, :
— ,
— ,
— .
:)