├── media
├── risk10.png
├── risk11.png
├── risk12.png
├── risk13.png
├── risk14.png
├── risk15.png
├── risk16.PNG
├── risk17.png
├── risk18.PNG
├── risk19.png
├── risk2.png
├── risk20.png
├── risk21.png
├── risk22.png
├── risk23.png
├── risk24.png
├── risk25.png
├── risk26.PNG
├── risk27.png
├── risk28.PNG
├── risk29.png
├── risk3.png
├── risk30.png
├── risk4.png
├── risk5.png
├── risk6.png
├── risk7.png
├── risk8.png
└── risk9.png
├── CODE_OF_CONDUCT.md
├── AssemblyInfo.cs
├── ThreatDetectionModule.sln
├── LICENSE
├── SECURITY.md
├── ThreatDetectionModule.csproj
├── UserRiskAnalyzer.cs
├── RiskyUserHelper.cs
├── __testcode40__.resx
├── .gitignore
└── README.md
/media/risk10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk10.png
--------------------------------------------------------------------------------
/media/risk11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk11.png
--------------------------------------------------------------------------------
/media/risk12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk12.png
--------------------------------------------------------------------------------
/media/risk13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk13.png
--------------------------------------------------------------------------------
/media/risk14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk14.png
--------------------------------------------------------------------------------
/media/risk15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk15.png
--------------------------------------------------------------------------------
/media/risk16.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk16.PNG
--------------------------------------------------------------------------------
/media/risk17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk17.png
--------------------------------------------------------------------------------
/media/risk18.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk18.PNG
--------------------------------------------------------------------------------
/media/risk19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk19.png
--------------------------------------------------------------------------------
/media/risk2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk2.png
--------------------------------------------------------------------------------
/media/risk20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk20.png
--------------------------------------------------------------------------------
/media/risk21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk21.png
--------------------------------------------------------------------------------
/media/risk22.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk22.png
--------------------------------------------------------------------------------
/media/risk23.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk23.png
--------------------------------------------------------------------------------
/media/risk24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk24.png
--------------------------------------------------------------------------------
/media/risk25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk25.png
--------------------------------------------------------------------------------
/media/risk26.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk26.PNG
--------------------------------------------------------------------------------
/media/risk27.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk27.png
--------------------------------------------------------------------------------
/media/risk28.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk28.PNG
--------------------------------------------------------------------------------
/media/risk29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk29.png
--------------------------------------------------------------------------------
/media/risk3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk3.png
--------------------------------------------------------------------------------
/media/risk30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk30.png
--------------------------------------------------------------------------------
/media/risk4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk4.png
--------------------------------------------------------------------------------
/media/risk5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk5.png
--------------------------------------------------------------------------------
/media/risk6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk6.png
--------------------------------------------------------------------------------
/media/risk7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk7.png
--------------------------------------------------------------------------------
/media/risk8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk8.png
--------------------------------------------------------------------------------
/media/risk9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/adfs-sample-block-user-on-adfs-marked-risky-by-AzureAD-IdentityProtection/master/media/risk9.png
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Microsoft Open Source Code of Conduct
2 |
3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
4 |
5 | Resources:
6 |
7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
10 |
--------------------------------------------------------------------------------
/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 | using System.Security.Permissions;
4 |
5 | [assembly: ComVisible(false)]
6 | [assembly: AssemblyProduct("Microsoft (R) Windows (R) Operating System")]
7 | [assembly: AssemblyCopyright("Copyright (c) Microsoft Corporation. All rights reserved.")]
8 | [assembly: AssemblyCompany("Microsoft Corporation")]
9 | [assembly: AssemblyFileVersion("10.0.10011.16384")]
10 |
11 | [assembly: AssemblyDelaySign(false)]
12 | [assembly: AssemblyVersion("10.0.0.0")]
13 |
14 |
--------------------------------------------------------------------------------
/ThreatDetectionModule.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 11.00
3 | # Visual Studio 2010
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThreatDetectionModule", "ThreatDetectionModule.csproj", "{9D147DF5-F62A-41FE-91E2-86CE41A91D5A}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Any CPU = Debug|Any CPU
9 | Release|Any CPU = Release|Any CPU
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {9D147DF5-F62A-41FE-91E2-86CE41A91D5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13 | {9D147DF5-F62A-41FE-91E2-86CE41A91D5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
14 | {9D147DF5-F62A-41FE-91E2-86CE41A91D5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
15 | {9D147DF5-F62A-41FE-91E2-86CE41A91D5A}.Release|Any CPU.Build.0 = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
40 |
41 |
--------------------------------------------------------------------------------
/ThreatDetectionModule.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {9D147DF5-F62A-41FE-91E2-86CE41A91D5A}
8 | Library
9 | ThreatDetectionModule
10 | v4.7.2
11 | 10.0.0.0
12 | 512
13 | ThreatDetectionModule
14 |
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 | true
37 |
38 |
39 | TDMKey.snk
40 |
41 |
42 |
43 | False
44 | ..\Windows\ADFS\Microsoft.IdentityServer.dll
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/UserRiskAnalyzer.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.IdentityServer.Public.ThreatDetectionFramework;
2 | using Microsoft.VisualBasic.FileIO;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Net;
6 | using System.Threading.Tasks;
7 | using Microsoft.IdentityServer.Public;
8 | using System.Security.Claims;
9 |
10 | namespace ThreatDetectionModule
11 | {
12 | ///
13 | /// UserRiskAnalyzer is the main class implementing ThreatDetectionModule abstract class and IPreAuthenticationThreatDetectionModule and IPostAuthenticationThreatDetectionModule interfaces.
14 | /// This module will allow a "No risk" user to be able to login successfully, allow "Low risk" user to login after additional auth (MFA) and block "High risk" user
15 | ///
16 | public class UserRiskAnalyzer : Microsoft.IdentityServer.Public.ThreatDetectionFramework.ThreatDetectionModule, IPreAuthenticationThreatDetectionModule, IPostAuthenticationThreatDetectionModule
17 | {
18 |
19 | public override string VendorName => "Microsoft";
20 | public override string ModuleIdentifier => "UserRiskAnalyzer";
21 |
22 | ///
23 | /// ADFS calls this method while loading the module
24 | ///
25 | ///
26 | ///
27 | public override void OnAuthenticationPipelineLoad(ThreatDetectionLogger logger, ThreatDetectionModuleConfiguration configData)
28 | {
29 | }
30 |
31 |
32 | ///
33 | /// ADFS calls this method while unloading the module
34 | ///
35 | ///
36 | public override void OnAuthenticationPipelineUnload(ThreatDetectionLogger logger)
37 | {
38 | }
39 |
40 |
41 | ///
42 | /// ADFS calls this method when there is any change in the configuration.
43 | ///
44 | ///
45 | ///
46 | public override void OnConfigurationUpdate(ThreatDetectionLogger logger, ThreatDetectionModuleConfiguration configData)
47 | {
48 | }
49 |
50 | public Task EvaluatePreAuthentication(ThreatDetectionLogger logger, RequestContext requestContext, SecurityContext securityContext, ProtocolContext protocolContext, IList additionalClams)
51 | {
52 |
53 | try
54 | {
55 | RiskScore isRisky = RiskyUserHelper.GetRiskScore(securityContext.UserIdentifier);
56 |
57 | if (isRisky == RiskScore.High)
58 | {
59 | logger?.WriteAdminLogErrorMessage($"EvaluatePreAuthentication: Blocked request for user {securityContext.UserIdentifier}");
60 | return Task.FromResult(ThrottleStatus.Block);
61 | }
62 | logger?.WriteDebugMessage($"EvaluatePreAuthentication: Allowed request for user {securityContext.UserIdentifier}");
63 | return Task.FromResult(ThrottleStatus.Allow);
64 |
65 |
66 | }
67 | catch (Exception ex)
68 | {
69 | logger.WriteAdminLogErrorMessage(ex.ToString());
70 | throw;
71 | }
72 |
73 | throw new NotImplementedException();
74 | }
75 |
76 | Task IPostAuthenticationThreatDetectionModule.EvaluatePostAuthentication(ThreatDetectionLogger logger, RequestContext requestContext, SecurityContext securityContext, ProtocolContext protocolContext, AuthenticationResult authenticationResult, IList additionalClams)
77 | {
78 | try
79 | {
80 | RiskScore isRisky = RiskyUserHelper.GetRiskScore(securityContext.UserIdentifier);
81 |
82 | if (isRisky == RiskScore.High || isRisky == RiskScore.Medium)
83 | {
84 | logger?.WriteAdminLogErrorMessage($"EvaluatePostAuthentication: Risk Score {isRisky} returned for user {securityContext.UserIdentifier}");
85 |
86 |
87 | }
88 | else
89 | {
90 | logger?.WriteDebugMessage($"EvaluatePostAuthentication: Risk Score {isRisky} returned for user {securityContext.UserIdentifier}");
91 | }
92 | return Task.FromResult(isRisky);
93 |
94 |
95 | }
96 | catch (Exception ex)
97 | {
98 | logger.WriteAdminLogErrorMessage(ex.ToString());
99 | throw;
100 | }
101 |
102 | throw new NotImplementedException();
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/RiskyUserHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Net;
5 | using System.Text;
6 | using System.Web.Script.Serialization;
7 | using Microsoft.IdentityServer.Public.ThreatDetectionFramework;
8 | //include dlls System.Web.Extensions
9 |
10 | namespace ThreatDetectionModule
11 | {
12 | public enum RiskLevel
13 | {
14 | None,
15 | Low,
16 | Medium,
17 | High
18 | }
19 |
20 | internal static class RiskyUserHelper
21 | {
22 | internal static string TenantName = "[Enter Azure AD Tenant Name]";
23 | internal static string ClientId = "[Enter Application (client) Id]";
24 | internal static string ClientSecret = "[Enter Application (client) Secret]";
25 | internal static string LoginURL = String.Format("https://login.microsoft.com/{0}/oauth2/token?api-version=1.0", TenantName);
26 | internal class RiskyList
27 | {
28 | public Dictionary[] Value { get; set; }
29 | }
30 |
31 | ///
32 | /// Gets the risk of a user by lookoing at the IP data from AAD
33 | ///
34 | /// UPN of the user
35 | ///
36 | public static RiskScore GetRiskScore(string upn)
37 | {
38 |
39 | Dictionary accessTokenResponse = GetAccessToken();
40 | RiskyList list = GetRiskyUsers(accessTokenResponse["token_type"], accessTokenResponse["access_token"]);
41 | Dictionary riskyUsers = BuildRiskyData(list);
42 | RiskScore level = RiskScore.NotEvaluated;
43 | if (null != riskyUsers)
44 | {
45 | if (riskyUsers.ContainsKey(upn))
46 | {
47 | level = riskyUsers[upn];
48 | }
49 | }
50 | return level;
51 | }
52 |
53 | static Dictionary BuildRiskyData(RiskyList list)
54 | {
55 | Dictionary riskyUserData = new Dictionary();
56 | foreach (Dictionary user in list.Value)
57 | {
58 | RiskScore level = RiskScore.NotEvaluated;
59 | if (user.ContainsKey("userPrincipalName") && !String.IsNullOrEmpty(user["userPrincipalName"]))
60 | {
61 | if (!String.IsNullOrEmpty(user["riskLevel"]))
62 |
63 | {
64 | if (String.Compare(user["riskLevel"], "high", StringComparison.OrdinalIgnoreCase) == 0)
65 | {
66 | level = RiskScore.High;
67 | }
68 | else if (String.Compare(user["riskLevel"], "low", StringComparison.OrdinalIgnoreCase) == 0)
69 | {
70 | level = RiskScore.Low;
71 | }
72 | else if (String.Compare(user["riskLevel"], "medium", StringComparison.OrdinalIgnoreCase) == 0)
73 | {
74 | level = RiskScore.Medium;
75 | }
76 | riskyUserData.Add(user["userPrincipalName"], level);
77 | }
78 | }
79 | }
80 |
81 | return riskyUserData;
82 | }
83 |
84 | // Gets the access token which can be used to get the Risky user information
85 | static Dictionary GetAccessToken()
86 | {
87 | string body = String.Format("resource=https://graph.microsoft.com&grant_type=client_credentials&client_id={0}&client_secret={1}", ClientId, ClientSecret);
88 | byte[] bodyBytes = Encoding.UTF8.GetBytes(body);
89 | var req = HttpWebRequest.Create(LoginURL);
90 |
91 | req.ContentType = "application/x-www-form-urlencoded";
92 | req.ContentLength = bodyBytes.Length;
93 | req.Method = "POST";
94 | req.GetRequestStream().Write(bodyBytes, 0, bodyBytes.Length);
95 |
96 | var response = req.GetResponse();
97 | Dictionary jsonResponse = new Dictionary();
98 | using (Stream stream = response.GetResponseStream())
99 | {
100 | using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
101 | {
102 | String responseString = reader.ReadToEnd();
103 | JavaScriptSerializer json_serializer = new JavaScriptSerializer();
104 | jsonResponse = json_serializer.Deserialize>(responseString);
105 | }
106 | }
107 |
108 | return jsonResponse;
109 | }
110 |
111 | // Get the Risky user data from the graph
112 | static RiskyList GetRiskyUsers(string tokenType, string accessToken)
113 | {
114 | var riskyReq = HttpWebRequest.Create("https://graph.microsoft.com/beta/riskyUsers");
115 | riskyReq.Headers.Add("Authorization", String.Format("{0} {1}", tokenType, accessToken));
116 |
117 | var responseRisky = riskyReq.GetResponse();
118 | using (Stream stream = responseRisky.GetResponseStream())
119 | {
120 | using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
121 | {
122 | String responseString = reader.ReadToEnd();
123 | JavaScriptSerializer json_serializer = new JavaScriptSerializer();
124 | return json_serializer.Deserialize(responseString);
125 | }
126 | }
127 | }
128 | }
129 | }
--------------------------------------------------------------------------------
/__testcode40__.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | __TESTCODE__
122 |
123 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Aa][Rr][Mm]/
27 | [Aa][Rr][Mm]64/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Ll]og/
32 | [Ll]ogs/
33 |
34 | # Visual Studio 2015/2017 cache/options directory
35 | .vs/
36 | # Uncomment if you have tasks that create the project's static files in wwwroot
37 | #wwwroot/
38 |
39 | # Visual Studio 2017 auto generated files
40 | Generated\ Files/
41 |
42 | # MSTest test Results
43 | [Tt]est[Rr]esult*/
44 | [Bb]uild[Ll]og.*
45 |
46 | # NUnit
47 | *.VisualState.xml
48 | TestResult.xml
49 | nunit-*.xml
50 |
51 | # Build Results of an ATL Project
52 | [Dd]ebugPS/
53 | [Rr]eleasePS/
54 | dlldata.c
55 |
56 | # Benchmark Results
57 | BenchmarkDotNet.Artifacts/
58 |
59 | # .NET Core
60 | project.lock.json
61 | project.fragment.lock.json
62 | artifacts/
63 |
64 | # StyleCop
65 | StyleCopReport.xml
66 |
67 | # Files built by Visual Studio
68 | *_i.c
69 | *_p.c
70 | *_h.h
71 | *.ilk
72 | *.meta
73 | *.obj
74 | *.iobj
75 | *.pch
76 | *.pdb
77 | *.ipdb
78 | *.pgc
79 | *.pgd
80 | *.rsp
81 | *.sbr
82 | *.tlb
83 | *.tli
84 | *.tlh
85 | *.tmp
86 | *.tmp_proj
87 | *_wpftmp.csproj
88 | *.log
89 | *.vspscc
90 | *.vssscc
91 | .builds
92 | *.pidb
93 | *.svclog
94 | *.scc
95 |
96 | # Chutzpah Test files
97 | _Chutzpah*
98 |
99 | # Visual C++ cache files
100 | ipch/
101 | *.aps
102 | *.ncb
103 | *.opendb
104 | *.opensdf
105 | *.sdf
106 | *.cachefile
107 | *.VC.db
108 | *.VC.VC.opendb
109 |
110 | # Visual Studio profiler
111 | *.psess
112 | *.vsp
113 | *.vspx
114 | *.sap
115 |
116 | # Visual Studio Trace Files
117 | *.e2e
118 |
119 | # TFS 2012 Local Workspace
120 | $tf/
121 |
122 | # Guidance Automation Toolkit
123 | *.gpState
124 |
125 | # ReSharper is a .NET coding add-in
126 | _ReSharper*/
127 | *.[Rr]e[Ss]harper
128 | *.DotSettings.user
129 |
130 | # TeamCity is a build add-in
131 | _TeamCity*
132 |
133 | # DotCover is a Code Coverage Tool
134 | *.dotCover
135 |
136 | # AxoCover is a Code Coverage Tool
137 | .axoCover/*
138 | !.axoCover/settings.json
139 |
140 | # Visual Studio code coverage results
141 | *.coverage
142 | *.coveragexml
143 |
144 | # NCrunch
145 | _NCrunch_*
146 | .*crunch*.local.xml
147 | nCrunchTemp_*
148 |
149 | # MightyMoose
150 | *.mm.*
151 | AutoTest.Net/
152 |
153 | # Web workbench (sass)
154 | .sass-cache/
155 |
156 | # Installshield output folder
157 | [Ee]xpress/
158 |
159 | # DocProject is a documentation generator add-in
160 | DocProject/buildhelp/
161 | DocProject/Help/*.HxT
162 | DocProject/Help/*.HxC
163 | DocProject/Help/*.hhc
164 | DocProject/Help/*.hhk
165 | DocProject/Help/*.hhp
166 | DocProject/Help/Html2
167 | DocProject/Help/html
168 |
169 | # Click-Once directory
170 | publish/
171 |
172 | # Publish Web Output
173 | *.[Pp]ublish.xml
174 | *.azurePubxml
175 | # Note: Comment the next line if you want to checkin your web deploy settings,
176 | # but database connection strings (with potential passwords) will be unencrypted
177 | *.pubxml
178 | *.publishproj
179 |
180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
181 | # checkin your Azure Web App publish settings, but sensitive information contained
182 | # in these scripts will be unencrypted
183 | PublishScripts/
184 |
185 | # NuGet Packages
186 | *.nupkg
187 | # NuGet Symbol Packages
188 | *.snupkg
189 | # The packages folder can be ignored because of Package Restore
190 | **/[Pp]ackages/*
191 | # except build/, which is used as an MSBuild target.
192 | !**/[Pp]ackages/build/
193 | # Uncomment if necessary however generally it will be regenerated when needed
194 | #!**/[Pp]ackages/repositories.config
195 | # NuGet v3's project.json files produces more ignorable files
196 | *.nuget.props
197 | *.nuget.targets
198 |
199 | # Microsoft Azure Build Output
200 | csx/
201 | *.build.csdef
202 |
203 | # Microsoft Azure Emulator
204 | ecf/
205 | rcf/
206 |
207 | # Windows Store app package directories and files
208 | AppPackages/
209 | BundleArtifacts/
210 | Package.StoreAssociation.xml
211 | _pkginfo.txt
212 | *.appx
213 | *.appxbundle
214 | *.appxupload
215 |
216 | # Visual Studio cache files
217 | # files ending in .cache can be ignored
218 | *.[Cc]ache
219 | # but keep track of directories ending in .cache
220 | !?*.[Cc]ache/
221 |
222 | # Others
223 | ClientBin/
224 | ~$*
225 | *~
226 | *.dbmdl
227 | *.dbproj.schemaview
228 | *.jfm
229 | *.pfx
230 | *.publishsettings
231 | orleans.codegen.cs
232 |
233 | # Including strong name files can present a security risk
234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
235 | #*.snk
236 |
237 | # Since there are multiple workflows, uncomment next line to ignore bower_components
238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
239 | #bower_components/
240 |
241 | # RIA/Silverlight projects
242 | Generated_Code/
243 |
244 | # Backup & report files from converting an old project file
245 | # to a newer Visual Studio version. Backup files are not needed,
246 | # because we have git ;-)
247 | _UpgradeReport_Files/
248 | Backup*/
249 | UpgradeLog*.XML
250 | UpgradeLog*.htm
251 | ServiceFabricBackup/
252 | *.rptproj.bak
253 |
254 | # SQL Server files
255 | *.mdf
256 | *.ldf
257 | *.ndf
258 |
259 | # Business Intelligence projects
260 | *.rdl.data
261 | *.bim.layout
262 | *.bim_*.settings
263 | *.rptproj.rsuser
264 | *- [Bb]ackup.rdl
265 | *- [Bb]ackup ([0-9]).rdl
266 | *- [Bb]ackup ([0-9][0-9]).rdl
267 |
268 | # Microsoft Fakes
269 | FakesAssemblies/
270 |
271 | # GhostDoc plugin setting file
272 | *.GhostDoc.xml
273 |
274 | # Node.js Tools for Visual Studio
275 | .ntvs_analysis.dat
276 | node_modules/
277 |
278 | # Visual Studio 6 build log
279 | *.plg
280 |
281 | # Visual Studio 6 workspace options file
282 | *.opt
283 |
284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
285 | *.vbw
286 |
287 | # Visual Studio LightSwitch build output
288 | **/*.HTMLClient/GeneratedArtifacts
289 | **/*.DesktopClient/GeneratedArtifacts
290 | **/*.DesktopClient/ModelManifest.xml
291 | **/*.Server/GeneratedArtifacts
292 | **/*.Server/ModelManifest.xml
293 | _Pvt_Extensions
294 |
295 | # Paket dependency manager
296 | .paket/paket.exe
297 | paket-files/
298 |
299 | # FAKE - F# Make
300 | .fake/
301 |
302 | # CodeRush personal settings
303 | .cr/personal
304 |
305 | # Python Tools for Visual Studio (PTVS)
306 | __pycache__/
307 | *.pyc
308 |
309 | # Cake - Uncomment if you are using it
310 | # tools/**
311 | # !tools/packages.config
312 |
313 | # Tabs Studio
314 | *.tss
315 |
316 | # Telerik's JustMock configuration file
317 | *.jmconfig
318 |
319 | # BizTalk build output
320 | *.btp.cs
321 | *.btm.cs
322 | *.odx.cs
323 | *.xsd.cs
324 |
325 | # OpenCover UI analysis results
326 | OpenCover/
327 |
328 | # Azure Stream Analytics local run output
329 | ASALocalRun/
330 |
331 | # MSBuild Binary and Structured Log
332 | *.binlog
333 |
334 | # NVidia Nsight GPU debugger configuration file
335 | *.nvuser
336 |
337 | # MFractors (Xamarin productivity tool) working folder
338 | .mfractor/
339 |
340 | # Local History for Visual Studio
341 | .localhistory/
342 |
343 | # BeatPulse healthcheck temp database
344 | healthchecksdb
345 |
346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
347 | MigrationBackup/
348 |
349 | # Ionide (cross platform F# VS Code tools) working folder
350 | .ionide/
351 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | page_type: sample
3 | languages: csharp
4 | products: dotnet
5 | ---
6 |
7 | # Build AD FS plug-in to block authentication or enforce MFA based on user risk level determined by Azure AD Identity Protection
8 |
9 | Build your own plug-in with [AD FS Risk Assessment Model](https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/development/ad-fs-risk-assessment-model) that uses the risk level of a user determined by [Azure AD Identity Protection](https://docs.microsoft.com/en-us/azure/active-directory/identity-protection/overview-identity-protection) to allow or block authentication or enforce additional authentication (MFA) while authenticating the user againsts AD FS.
10 |
11 | The plug-in once registered with AD FS runs in line with AD FS authentication process. For any user authenticating against AD FS, the plug-in pulls in the Risk Level of the user using the Azure AD Identity Protection [riskyUser API](https://docs.microsoft.com/en-us/graph/api/resources/riskyuser?view=graph-rest-beta) and initiates one of the follwing actions
12 | - Blocks authentication if user's risk level is “high”
13 | - Enforces additional authentication (MFA) if user's risk level is “low” or “medium”
14 | - Allows authentication if user's risk level is "none", "hidden" or "unknownFutureValue"
15 |
16 | >[!NOTE]
17 | >This sample is only to illustrate how cloud intelligence from Azure AD Identity Protection can be used to further strengthen the AD FS authentication process. By no means is this sample plug-in we are building an enterprise ready solution.
18 |
19 |
20 | ## Prerequisites
21 |
22 | - AD FS 2019 installed and configured
23 | - Synchronize AD (on-prem) users with Azure AD using synchronization tools such as [Azure AD Connect](https://docs.microsoft.com/en-us/azure/active-directory/hybrid/whatis-azure-ad-connect)
24 | - Azure AD Premium P2 license to be able to call [riskyUser API](https://docs.microsoft.com/en-us/graph/api/resources/riskyuser?view=graph-rest-beta) (https://graph.microsoft.com/beta/riskyUsers)
25 | >[!NOTE]
26 | >This sample plug-in gets the complete list of risky users for each authentication which can cause delay in authentication process. Therefore, the plug-in should be tested against an Azure AD tenant with a few number of users to avoid delays or should be optimized to use [Get riskyUser method](https://docs.microsoft.com/en-us/graph/api/riskyusers-get?view=graph-rest-beta&tabs=http) that gets the details of a specific user
27 | - Configure additional authentication method for AD FS such as [Azure MFA](https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/configure-ad-fs-and-azure-mfa)
28 | - .NET Framework 4.7 and above
29 | - Visual Studio
30 |
31 |
32 | ## Setting up the sample
33 |
34 | ### Build plug-in dll
35 |
36 | The following procedure will walk you through building a sample plug-in dll.
37 |
38 | 1. Download the [sample](https://github.com/Microsoft/adfs-sample-RiskAssessmentModel-RiskyIPBlock)
39 |
40 | 2. Open the project `ThreatDetectionModule.sln` using Visual Studio
41 |
42 | 3. Remove the `Microsoft.IdentityServer.dll` from the Solutions Explorer as shown below:
43 | 
44 |
45 | 4. Add reference to the `Microsoft.IdentityServer.dll` of your AD FS as shown below
46 |
47 | a. Right click on **References** in **Solutions Explorer** and select **Add Reference…**
48 | 
49 |
50 | b. On the **Reference Manager** window select **Browse**. In the **Select the files to reference…** dialogue, select `Microsoft.IdentityServer.dll` from your AD FS installation folder (in my case **C:\Windows\ADFS**) and click **Add**.
51 |
52 | >[!NOTE]
53 | >In my case I am building the plug-in on the AD FS server itself. If your development environment is on a different server, copy the `Microsoft.IdentityServer.dll` from your AD FS installation folder on AD FS server on to your development box.
54 |
55 | 
56 |
57 | c. Click **OK** on the **Reference Manager** window after making sure `Microsoft.IdentityServer.dll` checkbox is selected
58 | 
59 |
60 | 5. Open **RiskyUserHelper.cs** from the **Solutions Explorer** to update the Azure AD tenant name, Client ID and Client Secret
61 | 
62 |
63 | To get these perform the following steps as Administrator in **[Azure Portal](https://portal.azure.com/)**
64 |
65 | a. To get **Azure AD tenant name**, go to **[Azure Active Directory](https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/Overview)** blade and select **Properties** from the **Manage** section on the left navigation pane. Tenant name is the value in **Name** field under **Directory properties**)
66 | 
67 |
68 | b. To get the **Client ID** we first need to register the plug-in in Azure Active Directory. To do so, go to **[App Registration](https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade)**, click **New Registration**
69 | 
70 |
71 | On **New Registration**, enter a name for the plug-in and click **Register** (Note - For other fields, I am keeping the default values)
72 | 
73 |
74 | Once registered, get the **Client ID** for the registered plug-in as shown below
75 | 
76 |
77 | c. To get the **Client Secret** click **Certificates & secrets** from the **Manage** section on the left navigation pane as shown below
78 | 
79 |
80 | On **Certificates & secrets** blade, click **New client secret** and follow the process to generate the secret
81 | 
82 |
83 | Once generated, get the secret to update in the **RiskyUserHelper.cs** file.
84 |
85 | d. Though we have registered the plug-in in Azure Active Directory, we also need to provide it permission to call the Microsoft Graph API i.e. the riskyUser API
86 |
87 | To provide permission, click on **API permissions** from the **Manage** section on the left navigation pane. Then click **Add a permission**
88 | 
89 |
90 | On **Request API permissions** blade, select **Microsoft Graph**
91 | 
92 |
93 | Next, select **Application permissions** and search **identityriskyuser** under **Select permissions**. Select checkbox for **IdentityRiskyUser.Read.All** permission and click **Add permissions**
94 | 
95 |
96 | Lastly, click on **API permissions** from the **Manage** section on the left navigation pane. Select the **IdentityRiskyUser.Read.All** permission row and click on **Grant admin consent for [tenant name]**. Click **Yes**
97 | 
98 |
99 |
100 | 6. All the classes and references are now in place to do a build. However, since the output of this project is a dll, it will have to be installed into the **Global Assembly Cache**, or GAC, of the AD FS server and the dll needs to be signed first. This can be done as follows:
101 |
102 | a. **Right-click** on the name of the project, ThreatDetectionModule. From the menu, click **Properties**.
103 | 
104 |
105 | b. From the **Properties** page, click **Signing**, on the left, and then check the checkbox marked **Sign the assembly**. From the **Choose a strong name key file**: pull down menu, select ****
106 | 
107 |
108 | c. In the **Create Strong Name Key dialogue**, type a name (you can choose any name) for the key, uncheck the checkbox **Protect my key file with password**. Then, click **OK**
109 | 
110 |
111 | d. Save the project as shown below
112 | 
113 |
114 | 7. Build the project by clicking **Build** and then **Rebuild Solution** as shown below
115 | 
116 |
117 | Check the **Output window**, at the bottom of the screen, to see if any errors occurred
118 | 
119 |
120 |
121 | The plug-in (dll) is now ready for use and is in the **\bin\Debug** folder of the project folder (In my case, that's **C:\extensions\ThreatDetectionModule\bin\Debug\ThreatDetectionModule.dll**).
122 |
123 | The next step is to register this dll with AD FS, so it runs in line with AD FS authentication process.
124 |
125 | ### Register the plug-in dll with AD FS
126 |
127 | We need to register the dll in AD FS by using the `Register-AdfsThreatDetectionModule` PowerShell command on the AD FS server, however, before we register, we need to get the Public Key Token. This public key token was created when we created the key and signed the dll using that key. To learn what the Public Key Token for the dll is, you can use the **SN.exe** as follows
128 |
129 | 1. Copy the dll file from the **\bin\Debug** folder to another location (In my case copying it to **C:\extensions**)
130 |
131 | 2. Start the **Developer Command Prompt** for Visual Studio and go to the directory containing the **sn.exe** (In my case the directory is **C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.2 Tools**)
132 | 
133 |
134 | 3. Run the **SN** command with the **-T** parameter and the location of the file (In my case `SN -T "C:\extensions\ThreatDetectionModule.dll"`)
135 | 
136 | The command will provide you the public key token (For me, the **Public Key Token is 714697626ef96b35**)
137 |
138 | 4. Add the dll to the **Global Assembly Cache** of the AD FS server
139 | Our best practice would be that you create a proper installer for your project and use the installer to add the file to the GAC. Another solution is to use **Gacutil.exe** (more information on **Gacutil.exe** available [here](https://docs.microsoft.com/dotnet/framework/tools/gacutil-exe-gac-tool)) on your development machine. Since I have my visual studio on the same server as AD FS, I will be using **Gacutil.exe** as follows
140 |
141 | a. On Developer Command Prompt for Visual Studio and go to the directory containing the **Gacutil.exe** (In my case the directory is **C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.2 Tools**)
142 |
143 | b. Run the **Gacutil** command (In my case `Gacutil /IF C:\extensions\ThreatDetectionModule.dll`)
144 | 
145 |
146 | >[!NOTE]
147 | >If you have an AD FS farm, the above needs to be executed on each AD FS server in the farm.
148 |
149 | 5. Open **Windows PowerShell** and run the following command to register the dll
150 | ```
151 | Register-AdfsThreatDetectionModule -Name "" -TypeName ", , Version=10.0.0.0, Culture=neutral, PublicKeyToken=< Add the Public Key Token from Step 2. above>"
152 | ```
153 | In my case, the command is:
154 | ```
155 | Register-AdfsThreatDetectionModule -Name "RiskyUserPlugin" -TypeName "ThreatDetectionModule.UserRiskAnalyzer, ThreatDetectionModule, Version=10.0.0.0, Culture=neutral, PublicKeyToken=714697626ef96b35"
156 | ```
157 |
158 | >[!NOTE]
159 | >You need to register the dll only once, even if you have an AD FS farm.
160 |
161 | 6. Restart the AD FS service after registering the dll
162 |
163 | That's it, the dll is now registered with AD FS and ready for use!
164 |
165 | >[!NOTE]
166 | > If any changes are made to the plugin and the project is rebuilt, then the updated dll needs to be registered again. Before registering, you will need to unregister the current dll using the following command:
167 | >`
168 | UnRegister-AdfsThreatDetectionModule -Name ""
169 | >`
170 | >In my case, the command is:
171 | >```
172 | >UnRegister-AdfsThreatDetectionModule -Name "RiskyUserPlugin"
173 | >```
174 |
175 |
176 | ### Configure MFA policies in AD FS
177 |
178 | The last step in setting up the sample is to configure the policies in AD FS to trigger additional authentication (MFA) when the user risk level is either "low" or "medium". To do so, open **Windows PowerShell** on AD FS server and run the following command
179 | ```
180 | Set-AdfsRelyingPartyTrust -TargetName -AdditionalAuthenticationRules 'exists([Type == "http://schemas.microsoft.com/ws/2017/04/identity/claims/riskscore", Value == "low"])=>issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", Value = "http://schemas.microsoft.com/claims/multipleauthn"); exists([Type == "http://schemas.microsoft.com/ws/2017/04/identity/claims/riskscore", Value == "medium"])=>issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", Value = "http://schemas.microsoft.com/claims/multipleauthn"); exists([Type == "http://schemas.microsoft.com/ws/2017/04/identity/claims/riskscore", Value == "high"])=>issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", Value = "http://schemas.microsoft.com/claims/multipleauthn");'
181 | ```
182 | In my case, the command is:
183 | ```
184 | Set-AdfsRelyingPartyTrust -TargetName Claimsxray -AdditionalAuthenticationRules 'exists([Type == "http://schemas.microsoft.com/ws/2017/04/identity/claims/riskscore", Value == "low"])=>issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", Value = "http://schemas.microsoft.com/claims/multipleauthn"); exists([Type == "http://schemas.microsoft.com/ws/2017/04/identity/claims/riskscore", Value == "medium"])=>issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", Value = "http://schemas.microsoft.com/claims/multipleauthn"); exists([Type == "http://schemas.microsoft.com/ws/2017/04/identity/claims/riskscore", Value == "high"])=>issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", Value = "http://schemas.microsoft.com/claims/multipleauthn");'
185 | ```
186 |
187 |
188 | ## Running the sample
189 |
190 | For this demonstration, I will be using [AD FS Help Claims X-Ray tool](https://adfshelp.microsoft.com/ClaimsXray) to initiate authentication request. If you would like to use the X-Ray tool, please follow the instructions in step 1 **Federation Services Configuration** to create a relying party trust for the service in your federation deployment.
191 |
192 | 1. Enter federation server instance and hit **Test Authentication** in step 2 of Claims X-Ray tool
193 | 
194 |
195 | 2. On the login page, enter the user id and password of a non risky user (risk level = none)
196 | 
197 |
198 | The user should be able to log in.
199 |
200 | 3. Repeat step 1 above and on the login page enter a user id and password of a low risk user (risk level = Low)
201 |
202 | >[!NOTE]
203 | >To check the risk level of a user, go to **[Risky users report](https://portal.azure.com/#blade/Microsoft_AAD_IAM/SecurityMenuBlade/RiskyUsers)** in Azure Portal.
204 | >For testing purpose, to make a user risky (with risk level = Low) login with user credentials to Azure Portal from a [TOR browser](https://www.torproject.org/projects/torbrowser.html.en)
205 |
206 | The plug-in will trigger additional authentication as per the configuration (In my case I have configured Azure MFA)
207 | 
208 |
209 | Once authenticated, the user should be able to log in.
210 |
211 | 4. Repeat step 1 above and on the login page enter a user id and password of a high risk user (risk level = High)
212 |
213 | >[!NOTE]
214 | >For testing purpose, to make a user risky (with risk level = High) login to **[Risky users report](https://portal.azure.com/#blade/Microsoft_AAD_IAM/SecurityMenuBlade/RiskyUsers)** in Azure Portal as an Administrator. Select the user you want to change the risk level to High and click **Confirm user compromised**
215 | >
216 |
217 | The plug-in will block the user from authenticating
218 | 
219 |
220 |
221 |
222 | ## Contributing
223 |
224 | This project welcomes contributions and suggestions. Most contributions require you to agree to a
225 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
226 | the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
227 |
228 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide
229 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
230 | provided by the bot. You will only need to do this once across all repos using our CLA.
231 |
232 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
233 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
234 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
235 |
--------------------------------------------------------------------------------