Skip to content

Commit 73772f8

Browse files
committed
Merge PR #98
2 parents 98767de + 9184f4e commit 73772f8

16 files changed

Lines changed: 100 additions & 28 deletions

RELEASE_NOTES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
# Release Notes
2+
### 4.4.0 - September 24 2019
3+
* Added support for MFA (@StevenRasmussen)
4+
25
### 4.3.14 - September 13 2019
36
* Added missing short-hands for BPF typings
47

@@ -41,6 +44,7 @@
4144
### 4.3.1 - April 16 2019
4245
* Fixed bug when using expand
4346

47+
4448
### 4.3.0 - March 11 2019
4549
* Added support for synchronous execution of XrmQuery. Should be used sparingly. (@majakubowski)
4650

docs/content/tool-usage.fsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ Here is the full list of arguments for configuring the tool:
2424
| username | u, usr | Username for the CRM system.
2525
| password | p, pwd | Password for the CRM system.
2626
| domain | d, dmn | Domain for the user.
27+
| mfaAppId | | Azure Application Id
28+
| mfaReturnUrl | | Return URL of the Azure Application
2729
| ap | | Authentication Provider Type
2830
| out | o | Output directory for the generated declaration files.
2931
| jsLib | jl | Output directory for the JavaScript library files (**XrmQuery files**)

files/XrmDefinitelyTyped.exe.config

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,7 @@
99
<add key="entities" value="account, contact" />
1010
<add key="web" value="" />
1111
<add key="jsLib" value="../src/lib" />
12+
<add key="mfaAppId" value="" />
13+
<add key="mfaReturnUrl" value=""/>
1214
</appSettings>
1315
</configuration>

nuget/Delegate.XrmDefinitelyTyped.nuspec

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
<file src="..\src\XrmDefinitelyTyped\bin\Release\FSharp.Core.dll" target="content\XrmDefinitelyTyped" />
2424
<file src="..\src\XrmDefinitelyTyped\bin\Release\Microsoft.Xrm.Sdk.dll" target="content\XrmDefinitelyTyped" />
2525
<file src="..\src\XrmDefinitelyTyped\bin\Release\Microsoft.Crm.Sdk.Proxy.dll" target="content\XrmDefinitelyTyped" />
26+
<file src="..\src\XrmDefinitelyTyped\bin\Release\Microsoft.Xrm.Sdk.Deployment.dll" target="content\XrmDefinitelyTyped" />
27+
<file src="..\src\XrmDefinitelyTyped\bin\Release\Microsoft.Xrm.Tooling.Connector.dll" target="content\XrmDefinitelyTyped" />
28+
<file src="..\src\XrmDefinitelyTyped\bin\Release\Microsoft.IdentityModel.Clients.ActiveDirectory.dll" target="content\XrmDefinitelyTyped" />
29+
<file src="..\src\XrmDefinitelyTyped\bin\Release\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll" target="content\XrmDefinitelyTyped" />
2630
<file src="..\src\XrmDefinitelyTyped\bin\Release\XrmDefinitelyTyped.exe" target="content\XrmDefinitelyTyped" />
2731
<file src="..\src\XrmDefinitelyTyped\bin\Release\XrmDefinitelyTyped.xml" target="content\XrmDefinitelyTyped" />
2832
</files>

paket.dependencies

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ nuget FSharp.Formatting
66

77
nuget FSharp.Core
88
nuget Microsoft.CrmSdk.CoreAssemblies >= 8
9+
nuget Microsoft.CrmSdk.Deployment >= 8
10+
nuget Microsoft.CrmSdk.XrmTooling.CoreAssembly >= 8
911
github fsharp/FAKE modules/Octokit/Octokit.fsx

paket.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ NUGET
3232
FSharpVSPowerTools.Core (2.3)
3333
FSharp.Compiler.Service (>= 2.0.0.3)
3434
Microsoft.CrmSdk.CoreAssemblies (9.0.2.3)
35+
Microsoft.CrmSdk.XrmTooling.CoreAssembly (9.0.2.3)
36+
Microsoft.CrmSdk.Deployment (9.0.2.3)
37+
Microsoft.IdentityModel.Clients.ActiveDirectory (2.22.302111727)
3538
Microsoft.NETCore.Platforms (2.1) - restriction: || (&& (< monoandroid) (< net45) (< netstandard1.2) (>= netstandard1.3) (< win8)) (&& (< monoandroid) (< net45) (< netstandard1.2) (>= netstandard1.4) (< win8)) (&& (< monoandroid) (< net45) (< netstandard1.2) (>= netstandard1.5) (< win8)) (&& (< monoandroid) (< net45) (< netstandard1.2) (>= netstandard1.6) (< win8)) (&& (< monoandroid) (< net45) (< netstandard1.3) (>= netstandard1.4) (< win8) (< wpa81)) (&& (< monoandroid) (< net45) (< netstandard1.3) (>= netstandard1.5) (< win8) (< wpa81)) (&& (< monoandroid) (< net45) (< netstandard1.3) (>= netstandard1.6) (< win8) (< wpa81)) (&& (< monoandroid) (< net45) (< netstandard1.4) (>= netstandard1.5) (< win8) (< wpa81)) (&& (< monoandroid) (< net45) (< netstandard1.4) (>= netstandard1.6) (< win8) (< wpa81)) (&& (< monoandroid) (< net45) (< netstandard1.5) (>= netstandard1.6) (< win8) (< wpa81)) (&& (< net45) (>= net46) (< netstandard1.3)) (&& (< net45) (>= net46) (< netstandard1.4)) (&& (< net45) (>= net461)) (&& (< net45) (>= netstandard1.1) (< netstandard1.2) (< win8)) (&& (< net45) (>= netstandard1.2) (< netstandard1.3) (< win8) (< wpa81)) (&& (< net45) (>= netstandard1.3) (< netstandard1.4) (< win8) (< wpa81)) (&& (< net45) (>= netstandard1.4) (< netstandard1.5) (< win8) (< wpa81)) (&& (< net45) (>= netstandard1.5) (< netstandard1.6) (< win8) (< wpa81)) (&& (< net45) (>= netstandard1.6) (< netstandard2.0) (< win8) (< wpa81)) (&& (< net45) (>= netstandard2.0)) (&& (>= net46) (< portable-net45+win8+wpa81)) (>= netcoreapp2.0) (&& (< netstandard1.0) (>= netstandard1.1) (< portable-net45+win8)) (&& (< netstandard1.0) (>= netstandard1.1) (>= win8)) (&& (< netstandard1.0) (>= netstandard1.1) (< win8)) (&& (>= netstandard1.1) (< portable-net45+win8+wpa81)) (&& (>= netstandard1.1) (>= wp8)) (&& (>= netstandard1.2) (< portable-net45+win8+wpa81)) (&& (< netstandard1.2) (>= uap10.0) (< win8)) (&& (>= netstandard1.3) (< portable-net45+win8+wpa81)) (&& (< netstandard1.3) (>= uap10.0)) (&& (< netstandard1.3) (< win8) (>= wpa81)) (&& (>= netstandard1.4) (< portable-net45+win8+wpa81)) (&& (>= netstandard1.5) (< portable-net45+win8+wpa81)) (&& (< netstandard1.5) (>= uap10.0)) (&& (>= netstandard1.6) (< portable-net45+win8+wp8+wpa81)) (&& (>= netstandard1.6) (< portable-net45+win8+wpa81)) (&& (< portable-net45+win8+wpa81) (>= uap10.0)) (>= uap10.1)
3639
Microsoft.NETCore.Targets (2.1) - restriction: || (&& (< monoandroid) (< monotouch) (< net45) (>= netstandard1.6) (< netstandard2.0) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (&& (< monoandroid) (< net45) (>= netstandard1.1) (< netstandard1.2) (< win8)) (&& (< monoandroid) (< net45) (>= netstandard1.2) (< netstandard1.3) (< win8) (< wpa81)) (&& (< monoandroid) (< net45) (< netstandard1.2) (>= netstandard1.3) (< win8)) (&& (< monoandroid) (< net45) (< netstandard1.2) (>= netstandard1.4) (< win8)) (&& (< monoandroid) (< net45) (< netstandard1.2) (>= netstandard1.5) (< win8)) (&& (< monoandroid) (< net45) (< netstandard1.2) (>= netstandard1.6) (< win8)) (&& (< monoandroid) (< net45) (>= netstandard1.3) (< netstandard1.4) (< win8) (< wpa81)) (&& (< monoandroid) (< net45) (< netstandard1.3) (>= netstandard1.4) (< win8) (< wpa81)) (&& (< monoandroid) (< net45) (< netstandard1.3) (>= netstandard1.5) (< win8) (< wpa81)) (&& (< monoandroid) (< net45) (< netstandard1.3) (>= netstandard1.6) (< win8) (< wpa81)) (&& (< monoandroid) (< net45) (>= netstandard1.4) (< netstandard1.5) (< win8) (< wpa81)) (&& (< monoandroid) (< net45) (< netstandard1.4) (>= netstandard1.5) (< win8) (< wpa81)) (&& (< monoandroid) (< net45) (< netstandard1.4) (>= netstandard1.6) (< win8) (< wpa81)) (&& (< monoandroid) (< net45) (>= netstandard1.5) (< netstandard1.6) (< win8) (< wpa81)) (&& (< monoandroid) (< net45) (< netstandard1.5) (>= netstandard1.6) (< win8) (< wpa81)) (&& (< net45) (>= net46) (< netstandard1.4)) (&& (>= net46) (< portable-net45+win8+wpa81)) (&& (>= netstandard1.1) (< portable-net45+win8+wpa81)) (&& (>= netstandard1.2) (< portable-net45+win8+wpa81)) (&& (< netstandard1.2) (>= uap10.0) (< win8)) (&& (>= netstandard1.3) (< portable-net45+win8+wpa81)) (&& (< netstandard1.3) (>= uap10.0) (< win8) (< wpa81)) (&& (>= netstandard1.4) (< portable-net45+win8+wpa81)) (&& (>= netstandard1.5) (< portable-net45+win8+wpa81)) (&& (< netstandard1.5) (>= netstandard1.6) (>= uap10.0)) (&& (< netstandard1.5) (>= uap10.0) (< uap10.1)) (&& (< netstandard1.5) (>= uap10.0) (< win8) (< wpa81)) (&& (>= netstandard1.6) (< portable-net45+win8+wpa81)) (&& (< portable-net45+win8+wpa81) (>= uap10.0))
3740
Microsoft.Win32.Primitives (4.3) - restriction: || (&& (< monoandroid) (< net45) (< netstandard1.2) (>= netstandard1.3) (< win8)) (&& (< net45) (>= net46) (< netstandard1.4)) (&& (< net45) (>= netstandard1.3) (< netstandard1.4) (< win8) (< wpa81)) (&& (< net45) (>= netstandard1.4) (< netstandard1.5) (< win8) (< wpa81)) (&& (< net45) (>= netstandard1.5) (< netstandard1.6) (< win8) (< wpa81)) (&& (< net45) (>= netstandard1.6) (< netstandard2.0) (< win8) (< wpa81)) (&& (< netstandard1.5) (>= uap10.0) (< uap10.1)) (&& (< netstandard1.5) (>= uap10.0) (< win8) (< wpa81))

src/XrmDefinitelyTyped/CommandLine/Arguments.fs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,16 @@ type Args private () =
127127
altCommands=[]
128128
description="Authentication Provider Type"
129129
required=false }
130+
131+
{ command="mfaAppId"
132+
altCommands=[]
133+
description="Azure Application Id"
134+
required=false }
135+
136+
{ command="mfaReturnUrl"
137+
altCommands=[]
138+
description="Return URL defined for the Azure Application"
139+
required=false }
130140
]
131141

132142

src/XrmDefinitelyTyped/CommandLine/Program.fs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ let getXrmAuth parsedArgs =
1818
username = Map.find "username" parsedArgs
1919
password = Map.find "password" parsedArgs
2020
domain = Map.tryFind "domain" parsedArgs
21+
mfaAppId = Map.tryFind "mfaAppId" parsedArgs
22+
mfaReturnUrl = Map.tryFind "mfaReturnUrl" parsedArgs
2123
ap = ap; }
2224

2325
let getRetrieveSettings parsedArgs =

src/XrmDefinitelyTyped/Crm/CrmAuth.fs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
module internal DG.XrmDefinitelyTyped.CrmAuth
1+
module DG.XrmDefinitelyTyped.CrmAuth
22

3+
open System
34
open System.Net
5+
open Microsoft.IdentityModel.Clients.ActiveDirectory
46
open Microsoft.Xrm.Sdk
57
open Microsoft.Xrm.Sdk.Client
8+
open Microsoft.Xrm.Tooling.Connector
9+
open Microsoft.Xrm.Sdk.WebServiceClient
610

711
// Get credentials based on provider, username, password and domain
812
let internal getCredentials provider username password domain =
@@ -35,15 +39,24 @@ let internal getOrganizationServiceProxy
3539

3640
match serviceManagement.AuthenticationType with
3741
| AuthenticationProviderType.ActiveDirectory ->
38-
new OrganizationServiceProxy(serviceManagement, ac.ClientCredentials)
42+
new OrganizationServiceProxy(serviceManagement, ac.ClientCredentials) :> IOrganizationService
3943
| _ ->
40-
new OrganizationServiceProxy(serviceManagement, ac.SecurityTokenResponse)
44+
new OrganizationServiceProxy(serviceManagement, ac.SecurityTokenResponse) :> IOrganizationService
45+
46+
// Get Organization Service Proxy using MFA
47+
let internal getOrganizationServiceProxyUsingMFA userName password (orgUrl:Uri) mfaAppId mfaReturnUrl =
48+
let mutable orgName = ""
49+
let mutable region = ""
50+
let mutable isOnPrem = false
51+
Utilities.GetOrgnameAndOnlineRegionFromServiceUri(orgUrl, &region, &orgName, &isOnPrem)
52+
let cacheFileLocation = System.IO.Path.Combine(System.IO.Path.GetTempPath(), orgName, "oauth-cache.txt")
53+
let mutable proxy = new CrmServiceClient(userName, CrmServiceClient.MakeSecureString(password), region, orgName, false, null, null, mfaAppId, new Uri(mfaReturnUrl), cacheFileLocation, null)
54+
proxy :> IOrganizationService
4155

4256
// Authentication
43-
let authenticate org ap username password domain =
44-
let m = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(org)
45-
let at = m.Authenticate(getCredentials ap username password domain)
46-
m,at
57+
let internal getServiceManagement org =
58+
ServiceConfigurationFactory.CreateManagement<IOrganizationService>(org)
4759

48-
let proxyInstance manager authToken =
49-
getOrganizationServiceProxy manager authToken
60+
let internal authenticate (serviceManagement:IServiceManagement<IOrganizationService>) ap username password domain =
61+
serviceManagement.Authenticate(getCredentials ap username password domain)
62+

src/XrmDefinitelyTyped/Crm/CrmBaseHelper.fs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ open Microsoft.Xrm.Sdk.Messages
1010
open Microsoft.Xrm.Sdk.Query
1111
open Microsoft.Xrm.Sdk.Metadata
1212
open Microsoft.Crm.Sdk.Messages
13+
open Microsoft.Xrm.Sdk.WebServiceClient
1314

1415
// Execute request
15-
let getResponse<'T when 'T :> OrganizationResponse> (proxy:OrganizationServiceProxy) request =
16-
proxy.Timeout <- TimeSpan(1,0,0)
16+
let getResponse<'T when 'T :> OrganizationResponse> (proxy:IOrganizationService) request =
17+
if(proxy :? OrganizationServiceProxy) then
18+
let orgProxy = proxy :?> OrganizationServiceProxy
19+
orgProxy.Timeout <- TimeSpan(1,0,0)
1720
(proxy.Execute(request)) :?> 'T
1821

1922
// Retrieve version
@@ -23,11 +26,11 @@ let retrieveVersion proxy =
2326
parseVersion resp.Version
2427

2528
// Retrieve data
26-
let internal retrieveMultiple proxy logicalName (query:QueryExpression) =
29+
let internal retrieveMultiple (proxy:IOrganizationService) logicalName (query:QueryExpression) =
2730
query.PageInfo <- PagingInfo()
2831

2932
let rec retrieveMultiple'
30-
(proxy:OrganizationServiceProxy) (query:QueryExpression) page cookie =
33+
(proxy:IOrganizationService) (query:QueryExpression) page cookie =
3134
seq {
3235
query.PageInfo.PageNumber <- page
3336
query.PageInfo.PagingCookie <- cookie
@@ -68,7 +71,7 @@ let internal getEntities
6871

6972
// Get all entities with a filter
7073
let internal getEntitiesFilter
71-
proxy (logicalName:string)
74+
(proxy:IOrganizationService) (logicalName:string)
7275
(cols:string list) (filter:Map<string,obj>) =
7376

7477
let f = FilterExpression()
@@ -89,7 +92,7 @@ let getAllEntityMetadataLight proxy =
8992
resp.EntityMetadata
9093

9194
// Retrieve all metadata for all entities
92-
let getAllEntityMetadata (proxy:OrganizationServiceProxy) =
95+
let getAllEntityMetadata (proxy:IOrganizationService) =
9396
let request = RetrieveAllEntitiesRequest()
9497
request.EntityFilters <- Microsoft.Xrm.Sdk.Metadata.EntityFilters.All
9598
request.RetrieveAsIfPublished <- false
@@ -176,7 +179,7 @@ let getSpecificEntitiesAndDependentMetadata proxy logicalNames =
176179

177180

178181
// Retrieve single entity metadata
179-
let getEntityLogicalNameFromId (proxy:OrganizationServiceProxy) metadataId =
182+
let getEntityLogicalNameFromId (proxy:IOrganizationService) metadataId =
180183
let request = RetrieveEntityRequest()
181184
request.MetadataId <- metadataId
182185
request.EntityFilters <- Microsoft.Xrm.Sdk.Metadata.EntityFilters.Entity
@@ -187,7 +190,7 @@ let getEntityLogicalNameFromId (proxy:OrganizationServiceProxy) metadataId =
187190

188191

189192
// Retrieves all the logical names of entities in a solution
190-
let retrieveSolutionEntities proxy solutionName =
193+
let retrieveSolutionEntities (proxy:IOrganizationService) solutionName =
191194
let solutionFilter = [("uniquename", solutionName)] |> Map.ofList
192195
let solutions =
193196
getEntitiesFilter proxy "solution"
@@ -212,7 +215,13 @@ let retrieveSolutionEntities proxy solutionName =
212215
let proxyHelper xrmAuth () =
213216
let ap = xrmAuth.ap ?| AuthenticationProviderType.OnlineFederation
214217
let domain = xrmAuth.domain ?| ""
215-
CrmAuth.authenticate
216-
xrmAuth.url ap xrmAuth.username
217-
xrmAuth.password domain
218-
||> CrmAuth.proxyInstance
218+
let mfaAppId = xrmAuth.mfaAppId ?| ""
219+
let mfaReturnUrl = xrmAuth.mfaReturnUrl ?| ""
220+
let proxyInstance =
221+
match mfaReturnUrl with
222+
| "" ->
223+
let manager = CrmAuth.getServiceManagement xrmAuth.url
224+
let authToken = CrmAuth.authenticate manager ap xrmAuth.username xrmAuth.password domain
225+
CrmAuth.getOrganizationServiceProxy manager authToken
226+
| _ -> CrmAuth.getOrganizationServiceProxyUsingMFA xrmAuth.username xrmAuth.password xrmAuth.url mfaAppId mfaReturnUrl
227+
proxyInstance

0 commit comments

Comments
 (0)