We have a Asp Net Core Web API server, and Angular Client. Asp Net Core Web API is setup to do Windows Authentication. This setup works on all browsers on PC, Mac and Android Devices, and shows below sign in prompt to enter windows user and password.
But on iPhone none of the browsers prompt for the user and password and so Angular Client is not able to do any API calls.
Angular Client: HttpInterceptor implementation that makes sure credentials are passed to cross origin web api.
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if ((this.authService.getConfig() !== undefined &&
request.url.indexOf(this.authService.getConfig().logURL) === -1)) {
const apiRoot = this.authService.getApiRoot();
const authReq = request.clone({
url: `${apiRoot}/${request.url}`,
withCredentials: true
});
return next.handle(authReq);
} else {
return next.handle(request);
}
}
Web API is setup to negotiate Windows Authentication
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
And IIS has Windows Authentication and Anonymous Authentication enabled
How can I debug this issue?
Through your description, and the surveys I've done and the explanations in this blog. It seems that this has something to do with the iOS operating system, where windows authentication received a restriction on the iPhone.
It's entirely possible to judge the browser's device in angular(like window.navigator.userAgent.toLowerCase();
), and if it's found to be an iPhone device, we display the form page we created ourselves, and then authenticate it.
My Test Code
FrontEnd code not angular, it just for testing login method.
@{
ViewData["Title"] = "Login";
}
<h2>Login</h2>
<form method="post" action="/WinLogin/Login">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
<br>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<br>
<input type="submit" value="Login">
</form>
Login Method
public class WinLoginController : Controller
{
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, out IntPtr phToken);
[HttpGet]
public IActionResult Login()
{
return View();
}
[HttpPost]
public IActionResult Login(string username, string password)
{
IntPtr tokenHandle = new IntPtr(0);
bool returnValue = LogonUser(username, ".", password, 2, 0, out tokenHandle);
if (!returnValue)
{
int ret = Marshal.GetLastWin32Error();
throw new Win32Exception(ret);
}
using (WindowsIdentity identity = new WindowsIdentity(tokenHandle))
{
var principal = new WindowsPrincipal(identity);
HttpContext.User = principal;
return RedirectToAction("Index", "Home");
}
}
}
Test Result