I need to set a cookie in a WKWebView on both iOS 10 an iOS 11. After reading this, I wrote different code for the 2 iOS versions, using a JavaScript script in iOS 10 and WKWebsiteDataStore in iOS 11.
While using iOS 10 I have no issue, with iOS 11 the web app sees the cookie I used in the previous session. I mean, if the first time I launch the app the cookie value is "A", the web app doesn't see the cookie; if I close the app and relaunch it with "B" as the new value of the cookie, the web app now reads "A" from the cookie. However, with the Web Inspector I see the right value of the cookie.
It seems that with the WKWebsiteDataStore the cookie is set too late; how can I solve this issue (without using the same code used in iOS 10 even in iOS 11)?
My code is:
let preferences = WKPreferences()
preferences.javaScriptEnabled = true
let configuration = WKWebViewConfiguration()
let userContentController = WKUserContentController()
configuration.preferences = preferences
if #available(iOS 11, *) {
if let cookie = cookie {
let dataStore = WKWebsiteDataStore.default()
dataStore.httpCookieStore.setCookie(cookie) {
configuration.websiteDataStore = dataStore
configuration.userContentController = userContentController
self.createAndLoadWebView(with: configuration)
}
}
} else {
if let cookie = cookie {
let script = getJSCookiesString(for: [cookie])
let cookieScript = WKUserScript(source: script, injectionTime: .atDocumentStart, forMainFrameOnly: false)
userContentController.addUserScript(cookieScript)
configuration.userContentController = userContentController
createAndLoadWebView(with: configuration)
}
}
And then:
private func createAndLoadWebView(with configuration: WKWebViewConfiguration) {
webView = WKWebView(frame: self.containerView.frame, configuration: configuration)
self.containerView.addSubview(webView)
let req = URLRequest(url: pageUrl)
webView.load(req)
}
Add same cookies in Request header, i faced same problem but after add cookies in header request page load normally.
Related
I am getting this error:
[AuthenticationSession] The provided scheme is not valid. A scheme
should not include special characters such as ":" or "/".
When trying to use ASWebAuthenticationSession for a SwiftUI project:
let authURL = URL(string: "https://login.microsoftonline.com/common")
let scheme = "msauth.com.xxxxxxx.Test1://auth"
self.session = ASWebAuthenticationSession.init(url: authURL!, callbackURLScheme: scheme, completionHandler: { callbackURL, error in
guard error == nil, let successURL = callbackURL else {
return
}
let oauthToken = URLComponents(string: (successURL.absoluteString))?.queryItems?.filter({$0.name == "code"}).first
print(oauthToken ?? "No OAuth Token")
})
The oAuth provider is Azure AD B2C where I have configured a mobile app for iOS / macOS.
I have followed these examples for:
Using ASWebAuthenticationSession with SwiftUI
ASWebAuthenticationSession for Web Login in iOS App
I have stayed away from the MSAL sample in GitHub because there is no SwiftUI example and the issue has been outstanding for a year.
Maybe I should choose a different option for AuthenticationServices:
I have two applications that are using WS Federation and I am working to migrate one of these applications over to .NET Core. These two applications need to be able to share cookies and this is where I am running into an issue on the .NET Core side.
This is a portion of my Startup.cs
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<Context>()
.AddDefaultTokenProviders();
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = new PathString("/Account/Login");
//LOGIN WORKS CORRECTLY WITH THE BELOW LINE COMMENTED
options.TicketDataFormat = new AuthTicketDataFormat();
options.Cookie.Name = "cookiename";
options.Cookie.Path = "/";
options.Cookie.Domain = "";
});
services.ConfigureExternalCookie(options => {
options.LoginPath = new PathString("/Account/Login");
//LOGIN WORKS CORRECTLY WITH THE BELOW LINE COMMENTED
options.TicketDataFormat = new AuthTicketDataFormat();
options.Cookie.Name = "cookiename";
options.Cookie.Path = "/";
options.Cookie.Domain = "";
});
services.AddAuthentication()
.AddWsFederation(options => {
// MetadataAddress represents the Active Directory instance used to authenticate users.
options.MetadataAddress = authentication.GetValue<string>("AdfsWsFedMetadataUri");
// Wtrealm is the app's identifier in the Active Directory instance.
// For ADFS, use the relying party's identifier, its WS-Federation Passive protocol URL:
options.Wtrealm = authentication.GetValue<string>("AdfsRelyingPartyIdentifier");
});
I am able to see that I do receive a cookie in the Network tab, but the issue I am having is that I am being put into an infinite loop because on my anonymous Callback endpoint I have the following:
var loginInfo = await this._signInManager.GetExternalLoginInfoAsync();
//loginInfo is always coming back as null
if (loginInfo == null) {
return RedirectToAction("Login");
}
It seems the issue is being caused by options.TicketDataFormat and creating a custom format for the cookie. The cookie seems to be created correctly with the ticketDataFormat, but getExternalLoginInfoAsync on signInManager is always returning null.
Any help or direction is greatly appreciated as I've been banging my head against the wall for a day trying to figure this out.
There appears to be an issue with iOS 11 (still an issue as of iOS 11.0.1), home screen web apps, and cookies. When a cookie is set from the server, iOS 11 seems to intermittently delete the cookie. Other times, when the server expires a cookie, iOS 11 appears to intermittently fail to delete the cookie. These two behaviors occur after closing and re-opening the home screen web app and don't seem to be reproducible in Safari. These behaviors also don't appear to be present in iOS 10 or iOS 9.
I am guessing that this is a bug in iOS 11, but was wondering if anyone else has happened upon this issue and has figured out how to work around it.
For example, this ASP.NET code creates and expires a cookie upon login and logout. When the Index URL is added to the home screen, and the app is closed and re-opened (i.e., the Index URL gets reloaded) after either logging in or logging out, the app will sometimes show in the incorrect state upon reloading (logged out after logging in, or still logged in after logging out).
public class HomeController : Controller
{
[Route("~/")]
public ActionResult Index()
{
var loginCookie = Request.Cookies["Login"];
if (loginCookie != null)
{
return View();
}
else
{
return Redirect("Login");
}
}
[Route("~/login/")]
public ActionResult Login()
{
return View();
}
[HttpPost]
[Route("~/login/")]
public ActionResult LoginComplete()
{
var authCookie = new HttpCookie("Login", "login token")
{
Expires = DateTime.Now.AddMinutes(20)
};
Response.Cookies.Add(authCookie);
return Redirect("~/");
}
[Route("~/logout/")]
public ActionResult Logout()
{
var authCookie = new HttpCookie("Login", "login token")
{
Expires = DateTime.Now.AddMinutes(-1000)
};
Response.Cookies.Add(authCookie);
return View();
}
}
Here is the full repo if anyone wants to try reproducing the issue. Keep in mind that this is an intermittent issue, and multiple attempts may be required.
I am struggling to set a cookie using Swift 3 into a WKWebView. I could not find any example using Swift 3 so using Swift - How to set cookie in NSMutableURLRequest as a starting point, this is what I have:
let url = URL(string: "https://s3-us-west-2.amazonaws.com/foo/helloworld.html")
/* Create cookie and place in cookie storage */
let cookieStorage = HTTPCookieStorage.shared
let cookieHeaderField = ["Set-Cookie": "somecookie=" + cookieString + ";"]
let cookie = HTTPCookie.cookies(withResponseHeaderFields: cookieHeaderField, for: url!)
cookieStorage.setCookies(cookie, for: url, mainDocumentURL: nil)
let urlRequest = URLRequest.init(url: url!)
theWebView.load(urlRequest)
However, when I use the Simulator and inspect it using Safari Develop, it states that I have no cookies set. Thoughts on what I screwed up on or that I failed to take into account?
Swift 3.0
Use the following line to set cookie for urlRequest:
urlRequest?.setValue("somecookie" + cookieString, forHTTPHeaderField: "Cookie")
I have this code which is working absolutely fine on Windows Phone 8.1.
Unfortunately it doesn't work on Windows 8.1. The response that i am getting from this request give me a page with session expired, the same way it would be without the cookie. The code seems to be fine but it looks like the cookie doesn't get set or I am missing something else...
Is there something that needs to be added to make it work for Windows Store apps?
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
using (var client = new HttpClient(handler))
{
client.DefaultRequestHeaders.Add("Cookie", value.ToString());
htmlPage = await client.GetStringAsync("https://www.someurl.com" + querystring);
}
Your code works fine to pass in headers, but not cookies. Try this code instead:
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer.Add(new Uri("http://www.microsoft.com"), new Cookie("MyCookieName", "MyCookieValue"));
using (var client = new HttpClient(handler))
{
htmlPage = await client.GetStringAsync("https://www.microsoft.com");
}
System.Net.Http seems to work differently on W8.1 than on WP8.1. I could never figure out the difference.
Nevertheless I rewrote my code using Windows.Web.Http, which is new on 8.1 and recommended to use. Here an example how to attach cookies with the new httpclient:
var bpf = new Windows.Web.Http.Filters.HttpBaseProtocolFilter();
var cm = bpf.CookieManager;
var cookie = new HttpCookie("name", ".example.com", "/") { Value = "value" };
cm.SetCookie(cookie);
var http = new HttpClient(bpf);
await http.PostAsync(new Uri("http://example.com/"), new HttpStringContent("content"));
As well as here a sample:
http://code.msdn.microsoft.com/windowsapps/HttpClient-sample-55700664