I'm trying to use the implicit authentication of the StackExchange API, and therefor I need to send the user to https://www.stackexchange.com/oauth?client_id=...&scope=...&redirect_uri=... (with actual values instead of '...'). Easy, just drag out a WebView in Interface Builder and implement -webView:didFinishLoadForFrame: from the WebFrameLoadDelegate protocol to track if we are at the redirect_uri already. That works exactly as I want it to. But the WebView internals don't. An error page from stackexchange.com/oauth:
Application Login Failure
An error occurred while login into an application.
Error Details:
error: invalid_request
error description: OAuth request must be over HTTPS
But I started the URL with https://:
- (void)awakeFromNib {
NSString *oauthAddress = #"https://www.stackexchange.com/oauth?client_id=...&scope=...&redirect_uri=...";
[loginWebView setMainFrameURL:oauthAddress];
}
I can't find any source that says you have to do something else to enable HTTPS on a standard WebView.
It is caused by the WebView internals: in -webView:didFinishLoadForFrame: I NSLog()' the current URL:
- (void)webView:(WebView *)webView didFinishLoadForFrame:(WebFrame *)webFrame {
NSString *currentURL = [[[[webFrame dataSource] request] URL] absoluteString];
NSLog(#"-webView:didStartProvisionalLoadForFrame:");
NSLog(#"Current URL: %#", currentURL);
if ([currentURL hasPrefix:#"https://stackexchange.com/oauth/login_success"]) {
NSLog(#"We did login!");
}
}
Output:
2013-03-05 15:31:55.493 MacOverflow[2164:a0f] -webView:didStartProvisionalLoadForFrame:
2013-03-05 15:31:55.495 MacOverflow[2164:a0f] Current URL: http://stackexchange.com/oauth?client_id=...scope=...&redirect_uri=...
What the?! WebKit removed the 's' from the protocol part of the URL! How to stop WebKit from doing so? I searched Apple's documentation on WebView (with Cmd+f) for 'https' (0 matches), 'ssl' (0 matches) and even 'secure' (again 0 matches). I'm kinda stuck here, but it must be possible. It would be ridiculous to provide such a sophisticated browser control, but force the developer to write a copy for supporting https (which is quite common nowadays IMO)!
How to make an HTTPS request using WebKit's WebView?
This is not related to WebKit.
Remove www. from your URL like so https://stackexchange.com/oauth and you should be fine. At least that works for me.
Related
I have a simple WKWebView in macOS. I'm facing issues with redirection when visiting a page without www that then redirects to the subdomain www.
As far as I could find out I'd simply have to allow the navigation request and the webView should handle everything itself. But the redirect never actually happens. The webView ends up in a redirect loop, calling didReceiveServerRedirectForProvisionalNavigation: over and over again until finally failing with Error Domain=NSURLErrorDomain Code=-1007 "too many HTTP redirects"
Safari, other browsers and clients do indeed succeed, what makes me believe that it's not a server issue.
Also when I enter the address redirected to directly, it does work without any issues.
I implemented the WKNavigationDelegate protocol as follows:
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
if ([navigationAction navigationType] == WKNavigationTypeOther) {
if ([[[[navigationAction request] URL] host] isEqualToString:[[[self webView] URL] host]]) {
decisionHandler(WKNavigationActionPolicyAllow);
NSLog(#"allowed");
return;
}
decisionHandler(WKNavigationActionPolicyCancel);
NSLog(#"cancelled: %#", [navigationAction request]);
}
else {
decisionHandler(WKNavigationActionPolicyAllow);
}
}
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
NSLog(#"provisional navigation started");
}
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation; {
NSLog(#"provisional navigation received redirect");
}
I'm expecting the webView to accept and actually follow the redirect after I answered using WKNavigationActionPolicyAllow.
When I execute a request the following happens:
decidePolicyForNavigationAction: for main domain name
I respond with allow
didStartProvisionalNavigation:
decidePolicyForNavigationAction: for redirect with subdomain
I respond with allow
didReceiveServerRedirectForProvisionalNavigation:
Back to 6.
Do I have to somehow "commit" the redirect or do it manually myself?
Any ideas or did I miss something completely?
Stupid me. Really. Embarrassingly stupid.
My table now has my face embossed.
My original code was cut down for overview until a point where I deleted my issue...
I'm working on a special use case where the host name is not in the URL. I connect to a multi-site web server via it's IP and set the Host header accordingly to get the desired page.
When redirected I copy the request, set the header accordingly and resend the request. Guess what? Responding to a redirect by sending the same Host: header will result in another redirect. Grr.
I'll leave this here for public amusement to a day or two
Background:
I'm upgrading my app to use WKWebview from UIWebview as it will no longer be accepted by App Store
The App Store will no longer accept new apps using UIWebView as of April 2020 and app updates using UIWebView as of December 2020.
Issue:
What happen is, I'm getting cookie return from Webview (WKWebview) after logged in. I will retrieve a token I need for API firing, however I'm constantly hitting HTTP 401 status for all the API(s) fired.
If I revert back to UIWebview, and repeat the same for login but re-using the SAME TOKEN from WKWebview. I'm getting HTTP 200 status. Purpose of re-using same token is to prove that is a valid token.
Noted that, I have not make any changes to the method calling API. It remains the same for both WKWebview and UIWebview. (Including the object request for POST method)
Am I missing something in WKWebview?
Do I need to set cookie or allow anything in specific?
Code snippet:
<WebView
style={{ width: this.state.webviewWidth }}
ref={(component) => {
this.webviewRef = component;
}}
source={{ uri: this.state.url }}
onLoadStart={this.webviewOnLoadStart}
onLoad={this.webviewOnLoadEnd}
onNavigationStateChange={this.onNavigationStateChange}
useWebKit={true}
sharedCookiesEnabled={true}
/>
Pacakge.json
"react-native": "0.61.5",
"react-native-webview": "^10.3.2",
"#react-native-community/cookies": "^3.0.0",
Apparently the issue is that WKWebview does not handle cookie passing into the request header for us. Hence I received 401 authentication failure every time when I reach the server.
Unfortunately React-Native-Webview does not has a way to handle this cookie header passing out of the box (Please correct me if I'm wrong). I'm fully aware of this 'custom header' function provided within the lib, unfortunately it didn't work as expected. The cookie is still not part of the request header.
My solution to this is as follow, did under method decidePolicyForNavigationAction:
Dive into native lib (React-Native-Webview)
Loop through all existing cookies within websiteDataStore.httpCookieStore
Look for my cookie (of course, you should know your cookie name)
Append the cookie into the HTTPHeaderField to your http request
Load the http request again!
if (#available(iOS 11.0, *)) {
[webView.configuration.websiteDataStore.httpCookieStore getAllCookies:^(NSArray<NSHTTPCookie *> * _Nonnull cookies) {
NSLog(#"All cookies in websiteDataStore %#", cookies);
for(NSHTTPCookie *cookie in cookies){
if([cookie.name isEqualToString:#"coookieName"]){
if([navigationAction.request valueForHTTPHeaderField:#"Cookie"] != nil ){
}else{
NSMutableURLRequest *req = [request mutableCopy];
NSString *newCookie = [NSString stringWithFormat:#"cookieName=%#" , cookie.value];
// As you can see, I'm appending the cookie value into header myself
[req addValue:newCookie forHTTPHeaderField:#"Cookie"];
[req setHTTPShouldHandleCookies:YES];
[webView loadRequest:req];
return;
}
}
}
}];
} else {
// Fallback on earlier versions
}
When I run a query against the iTunes Search API over SSL, most of the URL's returned are provided via HTTPS:
https://itunes.apple.com/search?term=rihanna
However, the artworkUrl results are served over HTTP and updating them manually throws an error since the SSL certificate doesn't match on the domain they're using.
Is there a way to grab these images over HTTPS instead of HTTP?
You have to replace the sub domain:
http://is<n> with https://is<n>-ssl
Example:
http://is5.mzstatic.com/image/thumb/Music117/v4/dd/48/4a/dd484afb-2313-0a1a-ccf1-ff28a02ae2ca/source/100x100bb.jpg
to
https://is5-ssl.mzstatic.com/image/thumb/Music117/v4/dd/48/4a/dd484afb-2313-0a1a-ccf1-ff28a02ae2ca/source/100x100bb.jpg
iTunes does not support the album art or song previews over HTTPS (yet).
The change over of the tools and links to HTTPS was recent (only four months ago):
http://www.apple.com/itunes/affiliates/resources/blog/secure-links-to-itunes---content-and-tools.html
New to SO and Swift - stumbled over this problem until finding this Q, and the answers above. The following worked for me:
func withHTTPS() -> URL? {
var components = URLComponents(url: self, resolvingAgainstBaseURL: true)
components?.scheme = "https"
let host = (components?.host)!
components?.host = host.replacingOccurrences(of: ".", with: "-ssl.", options: .caseInsensitive, range: host.range(of: "."))
return components?.url
}
called using:
guard let url = item.artworkURL.withHTTPS() else { return }
I need to send post web request from titanium mobile webview.
Created a webview and included the below html code (Upload.html)
<html>
<head>
<script>
function loadXMLDoc()
{
//alert('asdfsf');
var xmlhttp=new XMLHttpRequest();
xmlhttp.open("POST","https://www.mydomain.com",true);
xmlhttp.send('encrypted image string');
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
alert('xmlhttp'+xmlhttp.responseText);
}
}
}
</script>
</head>
<body onload="loadXMLDoc()">
<h1>Sample</h1>
</body></html>
and used in webview as follows:
var webview = Ti.UI.createWebView({
url : 'Upload.html',
height : 100,
width : 100,
top : 0,
left : 0
});
On creating the webview console shows
2013-02-07 17:36:20.906 WebviewSample[6575:1f43f] [WARN] Unable to securely connect to api.appcelerator.net with the latest TLS. Trying again with TLS1.0. It is highly suggested that the server be updated to the latest TLS support.
[ERROR] Analytics error sending request: A connection failure occurred: SSL problem (Possible causes may include a bad/expired/self-signed certificate, clock set to wrong date)
Although the console error may seem to be related to your webview I think it's not.
I think you have analytics enabled for your application and for some reason the SSL session is being rejected (time not correctly configured, etc.).
Disable analytics in your tiapp.xml and this error should not appear again, or try to figure out what is making the SSL connection to be rejected.
Second thought: If you're trying to post to an https domain and you're already having issues with your time config. it probably won't post anything through the webview because the SSL connection is also being rejected for the same reason as the analytics connection.
I'm trying to use SBApplication to tell a couple of browsers (Safari and Chrome) to open a given URL. However, the apps just treat it like a file url. Here's the pseudo/JSTalk code I'm using:
var safari = [SBApplication applicationWithBundleIdentifier:#"com.apple.Safari"];
var url = [NSURL URLWithString:#"http://apple.com/"];
[safari open:url]; // results in opening "file:///http/::apple.com:"
Any hints? Making a Safari.h file with sdp ( sdef /Applications/Safari.app | sdp -fh --basename "Safari" ) doesn't really help much to see what I can do.
Just read that you wish to open an URL using multiple browsers. Thus, my answer isn't of help here:
I'd propose to ask NSWorkspace to open the URL:
// make an URL
NSURL *someUrl = [NSURL URLWithString:#"http://my.server.vom/" ];
if ([[NSWorkspace sharedWorkspace] openURL:someURL]) {
NSLog(#"Fine. URL opened.");
} else {
// shouldn't happen
}
Regarding your problem: Did you try to pass a string to Safari, not an NSURL?