Fable bindings for ADAL.js (Azure Active Directory for Javascript)
paket add Fable.Import.Adal
or dotnet add package Fable.Import.Adal
This example is epecting ADAL.js to bee added as a script in index.html
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.15/js/adal.min.js"></script>
Once add we can authenticate with active directory and pass the resulting JWT to an API.
let tokenUri = "<API Token URI - Typically App Uri for the API>"
let authContext =
let config = createEmpty<adal.Adal.Config>
config.clientId <- "<Client ID>"
config.tenant <- Some "<Tenant ID>"
config.postLogoutRedirectUri <- Some window.location.origin
config.cacheLocation <- Some "localstorage"
adal.Adal.createAuthContext(config)
let withToken f =
let token = authContext.getCachedToken(tokenUri)
if token = null
then
authContext.acquireToken(tokenUri, fun _ token -> f token; None)
else f token
let getData endpoint f token =
promise {
let url = sprintf "http://localhost:5000/api/%s" endpoint
let props = [
Fetch.requestHeaders [
Fetch.Fetch_types.Authorization ("Bearer " + token)
]
]
let! data = Fetch.fetchAs<string[]> url props
return f data
} |> P.start
let init() =
let loginBut = document.getElementById("login") :?> HTMLButtonElement
let logoutBut = document.getElementById("logout") :?> HTMLButtonElement
let getDataBut = document.getElementById("getdata") :?> HTMLButtonElement
let getTradeBut = document.getElementById("gettrades") :?> HTMLButtonElement
let status = document.getElementById("status") :?> HTMLDivElement
let data = document.getElementById("data") :?> HTMLDivElement
let trade = document.getElementById("trades") :?> HTMLDivElement
authContext.handleWindowCallback()
if(authContext.isCallback(window.location.hash) && (authContext.getLoginError() <> null))
then ()
else status.innerText <- ("Error: " + authContext.getLoginError())
let user = authContext.getCachedUser()
if(user <> null)
then
withToken(fun token ->
status.innerText <- user.userName + " : " + token
getDataBut.disabled <- false
getTradeBut.disabled <- false
)
else
getDataBut.disabled <- true
getTradeBut.disabled <- true
status.innerText <- "No user, no cry!!!"
loginBut.addEventListener_click(fun _ -> printf "%s" "login"; authContext.login(); box())
logoutBut.addEventListener_click(fun _ -> getDataBut.disabled <- true;authContext.logOut(); box())
getDataBut.addEventListener_click (fun _ -> withToken <| getData "items" (fun d -> data.innerHTML <- ("<pre>" + (System.String.Join(System.Environment.NewLine, d)) + "</pre>")); box())
getTradeBut.addEventListener_click (fun _ -> withToken <| getData "trades" (fun d -> data.innerHTML <- ("<pre>" + (System.String.Join(System.Environment.NewLine, d)) + "</pre>")); box())
init()
See the samples directory for an example implementation