-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathCheck-PersonalAccount.ps1
215 lines (184 loc) · 9.89 KB
/
Check-PersonalAccount.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
Function Check-PersonalAccount {
<#
.SYNOPSIS
Given an SMTP address(es) will verify if they are associated with both a personal and work Microsoft account
.DESCRIPTION
For each SMTP address
Validate it's a fully formed SMTP address
Accesses the o365 login page (currently https://login.microsoftonline.com)
Gets all pertinent session data
Uses the SMTP address in the post to the login form for the o365 login page
Parses the response to check the following and returns the results
1. Is this address associated with both a personal and work account?
2. Is This address federated?
3. The a federated gateway associated with this SMTP address (if present)
.PARAMETER mail
The SMTP address to check
.PARAMETER O365LoginPage
The o365 login page (currently https://login.microsoftonline.com)
.PARAMETER Proxy
Proxy URL if needed
.PARAMETER UserAgent
Browser user agent if needed
.EXAMPLE
PS C:\> Check-PersonalAccount -mail "Jane.Doe@contoso.com","Jane.Doe@microsoft.com"
mail PersonalAccount FederatedAccount FederatedGateway
---- --------------- ---------------- ----------------
Jane.Doe@contoso.com False False
Jane.Doe@microsoft.com False True https://msft.sts.microsoft.com/adfs/ls/
Description
-----------
Will check the following SMTP addresses ("Jane.Doe@contoso.com","Jane.Doe@microsoft.com") verify if a personal account, an federated account, and a federated gateway exists
.NOTES
AUTHOR: John Mello
CREATED : 07/31/2019
CREATED BECAUSE:
Various non O365 related apps couldn't deal with the "Is this a personal or work account prompt".
So a method was needed to flag all users who had their corporate email address associated with a personal account
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true,ValueFromPipeline = $true,ValueFromPipelineByPropertyName = $true)]
[Alias("email","emailaddress")]
[string[]]$mail,
[String]$O365LoginPage = 'https://login.microsoftonline.com',
[String]$Proxy = '',
[String]$UserAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393'
)
Begin {
#region Functions
function isEmailAddress($object) {
#Taken from Tobias Weltner @ http://powershell.com/cs/media/p/389.aspx
($object -as [System.Net.Mail.MailAddress]).Address -eq $object -and $object -ne $null
}#Function
#endregion funtions
#region variables
#Default splat for all webactions
$WebSplat = @{
UseBasicParsing = $TRUE
MaximumRedirection = 1000
UseDefaultCredentials = $TRUE
TimeoutSec = 1000
ErrorAction = 'Stop'
Method = 'GET'
Verbose = $FALSE
}#$WebSplat
#Add other web request info as needed
if ($Proxy) {
$WebSplat.add('Proxy', $Proxy)
$WebSplat.add('ProxyUseDefaultCredentials',$TRUE)
}#if ($Proxy)
if ($UserAgent) { $WebSplat.add('UserAgent', $UserAgent) }
#Regexs for parsing the need form info
#$FlowTokenRegEx = '"sFT":"(?<FlowToken>.*)","sFTName":"flowToken"'
#$OGRequestRegEx = '"sCtx":"(?<OrginalRequest>.*)","iProductIcon"'
#$APICanaryRegEx = '"apiCanary":"(?<apiCanary>.*)","canary"'
$ConfigRegEx = '\$Config=(?<Config>{.*});'
#Array of know IfExistsResult results that point to federated address with a personal account
$DualAccountTest = @("5","6")
#Array of know IfExistsResult results that point to either just a personal or Federated account
#0 - Appears This is a federated only account
#1 - Appears This is a personal only account
$SingleAccountTest = @("0","1")
#endregion variables
}#begin
Process{
Foreach ($address in $mail) {
Write-Verbose "$address : *** STARTING ***"
Try {
#Object to return for each entry
$AddressResults = [PSCustomObject]@{
mail = $address
PersonalAccount = ''
FederatedAccount = ''
FederatedGateway = ''
}#$AddressResults = [PSCustomObject]@
Write-Verbose "$address : Verifying if a fully qualified Email addresses"
If (-not (isEmailAddress $address)) {
Throw "$address email address is not valid"
} #If (-not (isEmailAddress $address))
Write-Verbose "$address : Requesting $O365LoginPage"
$RedirectToFedGateway = Invoke-WebRequest $O365LoginPage -SessionVariable WebSession @WebSplat
$CurrentPage = $RedirectToFedGateway.BaseResponse.ResponseUri.Host
#Add the current session to all subsequent web commands
$WebSplat.Add('WebSession', $WebSession)
#Grab config file which will hold all the neccesary info for the login form
#$FlowTokenResults = [regex]::Match($RedirectToFedGateway.RawContent, $FlowTokenRegEx)
#$OGRequestrResults = [regex]::Match($RedirectToFedGateway.RawContent, $OGRequestRegEx)
#$APICanaryResults = [regex]::Match($RedirectToFedGateway.RawContent, $APICanaryRegEx)
Write-Verbose "$address : Parsing response for the login form info for this session"
$ConfigResults = [regex]::Match($RedirectToFedGateway.RawContent, $ConfigRegEx)
$ConfigFile = $ConfigResults.Groups['Config'] | ConvertFrom-Json
#Login body using info from the current session"
$LoginFOrm = @{
checkPhones = 'false'
country = "US"
flowToken = $ConfigFile.sFT
forceotclogin = 'false'
isCookieBannerShown = 'false'
isExternalFederationDisallowed = 'false'
isFidoSupported = 'false'
isOtherIdpSupported = 'true'
isRemoteNGCSupported = 'true'
originalRequest = $ConfigFile.sCtx
username = $address
}#$LoginFOrm
#Convert to JSON since sending it over as a hashtbale didn't work
$LoginFOrm = $LoginFOrm | ConvertTo-Json -ErrorAction Stop
$WebSplat.Add('Body', $LoginFOrm )
$WebSplat.Method = 'POST'
#Get the redirection URL to post the form to
$Sumbit = $ConfigFile.urlGetCredentialType
Write-Verbose "$address : Submiting login form for this address"
$SubmitForm = Invoke-WebRequest -Uri $Sumbit @WebSplat
Write-Verbose "$address : Parsing login form response"
if ($SubmitForm.StatusCode -eq 200) {
#TODO could be cleaned up and better research into what the various response info is
$FormData = $SubmitForm.Content | ConvertFrom-Json -ErrorAction Stop
#Check if a personal account
if ($FormData.IfExistsResult -in $DualAccountTest) {
$AddressResults.PersonalAccount = $TRUE
}#if ($FormData.IfExistsResult -in $PersonalAccountTest)
Elseif ($FormData.IfExistsResult -in $SingleAccountTest) {
$AddressResults.PersonalAccount = $False
}#Else
Else {
Write-Warning "$address : Unhandled IfExistsResult code returned - $($FormData.IfExistsResult)"
$AddressResults.PersonalAccount = "UNKNOWN"
}#Else
#Check if there is a federated gateway URL
if ($FormData.Credentials.FederationRedirectUrl) {
$AddressResults.FederatedGateway = ($FormData.Credentials.FederationRedirectUrl -split "\?")[0]
$AddressResults.FederatedAccount = $True
}#if ($FormData.Credentials.FederationRedirectUrl)
Else {
$AddressResults.FederatedAccount = $False
}#Else
}#if ($SubmitForm.StatusCode -eq 200)
Else {
Write-Warning "$address : 200 HTTP response not recieved (actual:$($SubmitForm.StatusCode))"
$AddressResults.PersonalAccount = "UNKNOWN"
$AddressResults.FederatedGateway = "UNKNOWN"
}#Else
}#Try
Catch {
Write-Warning "$address : Issue accessing URL ($O365LoginPage). Full error below:"
$_
$AddressResults.PersonalAccount = "ERROR"
$AddressResults.FederatedGateway = "ERROR"
}#Catch
#Clean WebSplat for resue
#Remove the websession and body from tthe splat
$WebSplat.remove('WebSession')
$WebSplat.remove('Body')
#reset the method to 'GET"
$WebSplat.Method = 'Get'
#Clear the websession variable
Clear-Variable WebSession -ErrorAction Stop
#return Results to the pipeline
$AddressResults
Write-Verbose "$address : *** END ***"
}#Foreach ($address in $mail)
}#Process
End{} #End
}#Function Check-PersonalAccount