Swift cookie set fails to overwrite existing cookie - uiwebview

I have the following code to save cookies but the cookie is not being saved. The get cookie code shows that my cookie is not present in the shared cookies. The "set cookie" is being printed but "get cookie" is not showing my cookie. I can get it to save a new cookie but not overwrite an existing cookie.
func setCookie() {
let infoModel = UserInfoManager.getUserInfoModel()
if infoModel != nil {
let ExpTime = TimeInterval(60 * 60 * 24 * 365)
let cookieProps: [HTTPCookiePropertyKey : Any] = [
HTTPCookiePropertyKey.domain: ".mydomain.com",
HTTPCookiePropertyKey.path: "/",
HTTPCookiePropertyKey.name: "DEV",
HTTPCookiePropertyKey.value: infoModel!.userAccessToken!,
HTTPCookiePropertyKey.secure: "TRUE",
HTTPCookiePropertyKey.expires: NSDate(timeIntervalSinceNow: ExpTime),
HTTPCookiePropertyKey.version: "0"
]
print("WEB REQUEST ACCESS TOKEN \(infoModel!.userAccessToken!)")
if let cookie = HTTPCookie(properties: cookieProps) {
HTTPCookieStorage.shared.setCookie(cookie)
print("\(cookie)")
print("GET COOKIE \(HTTPCookieStorage.shared.cookies)")
}
else {
print("set cookie failed")
}
....
}

I had to delete the cookie I wanted to overwrite first.
let cookieJar = HTTPCookieStorage.shared
for cookie in cookieJar.cookies! {
if cookie.name == "DEV" {
HTTPCookieStorage.shared.deleteCookie(cookie)
}
}

Related

Expiration of CachedURLResponse not working

I was trying to set custom headers for 'Cache-Control' to achieve a cache at client side(server side has 'Cache-Control: no-cache'). Trying to achieve following two major things.
Response of some of the end points should be cached in memory and
should have an expiration(user defined)
Once expiration time is over, then app should ignore the cache and should fetch data from server.
I followed this link and was able to achieve first target but somehow even after expiry app is still using cache and not triggering any API calls. Not sure if 'max-age' set in header is ignored by the app. Please guide me if I am missing something here.
Here are the code snippets.
Session Configuration:
let sessionConfiguration: URLSessionConfiguration = URLSessionConfiguration.ephemeral
sessionConfiguration.requestCachePolicy = .returnCacheDataElseLoad
sessionConfiguration.urlCache = .shared
self.currentURLSession = URLSession(configuration: sessionConfiguration, delegate: self, delegateQueue: nil)
Request:
if let urlPath = URL(string: <WEB_API_END_POINT>){
var aRequest = URLRequest(url: urlPath, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 60)
aRequest.addValue("private", forHTTPHeaderField: "Cache-Control")
let aTask = self.currentURLSession.dataTask(with: aRequest)
aTask.resume()
}
Caching logic:
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse, completionHandler: #escaping (CachedURLResponse?) -> Void) {
if proposedResponse.response.url?.path.contains("/employees") == true {
let updatedResponse = proposedResponse.response(withExpirationDuration: 60)
completionHandler(updatedResponse)
} else {
completionHandler(proposedResponse)
}
}
CachedURLResponse Extension:
extension CachedURLResponse {
func response(withExpirationDuration duration: Int) -> CachedURLResponse {
var cachedResponse = self
if let httpResponse = cachedResponse.response as? HTTPURLResponse, var headers = httpResponse.allHeaderFields as? [String : String], let url = httpResponse.url{
headers["Cache-Control"] = "max-age=\(duration)"
headers.removeValue(forKey: "Expires")
headers.removeValue(forKey: "s-maxage")
if let newResponse = HTTPURLResponse(url: url, statusCode: httpResponse.statusCode, httpVersion: "HTTP/1.1", headerFields: headers) {
cachedResponse = CachedURLResponse(response: newResponse, data: cachedResponse.data, userInfo: headers, storagePolicy: .allowedInMemoryOnly)
}
}
return cachedResponse
}
}
Was able to fix it at my own. Still sharing the answer in case if helps someone else in need.
Added 'Cache-Control' response header in server response and there we have 'max-age: 60', which indicates that response can be valid till 60 seconds only. So till 60 seconds, app will cache that data and after 60 seconds if making another request, this will fetch fresh data from server.
With that, At client side other than defining your cache policy, nothing else is required.
You can do this either for entire URL Session:
let sessionConfiguration: URLSessionConfiguration = URLSessionConfiguration.ephemeral
sessionConfiguration.requestCachePolicy = .useProtocolCachePolicy
sessionConfiguration.urlCache = .shared
self.currentURLSession = URLSession(configuration: sessionConfiguration, delegate: self, delegateQueue: nil)
Or can do it for specific request.
if let urlPath = URL(string: <WEB_API_END_POINT>) {
var aRequest = URLRequest(url: urlPath, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 60)
let aTask = self.currentURLSession.dataTask(with: aRequest)
aTask.resume()
}

Getting Missing Key-Pair-Id query parameter or cookie value error from cloudfront

Using cloudfront to serve private content from s3 bucket using signed cookies.
I am able to generate cookies, but when i request a resource, i get Missing Key-Pair-Id query parameter or cookie value error, either from node.js or even any client/browser/postman
const cloudFront = new AWS.CloudFront.Signer(
fs.readFileSync('./rsa-APKAIQSVJ2R3T6PYTOUQ.pem', 'utf8'),
fs.readFileSync('./pk-APKAIQSVJ2R3T6PYTOUQ.pem', 'utf8')
);
const policy = JSON.stringify({
Statement: [{
Resource: 'http*://d2q89b5pewg0ry.cloudfront.net/images/',
Condition: {
DateLessThan: {
'AWS:EpochTime': Math.floor(new Date().getTime() / 1000) + 60 * 60 * 3
}
},
}]
});
const cookie = cloudFront.getSignedCookie({
policy: policy
});
let cookieString = '';
for(var cookieKey in cookie)
{
cookieString += cookieKey + '=' + cookie[cookieKey] + ";";
}
return axios.get('https://d2q89b5pewg0ry.cloudfront.net/images/hikup.jpg',{
headers: {
Cookie: cookieString
}
}).then((response) => {
return response;
}).catch((error) => {
return error;
});
You're not using the full constructor, check below:
CloudFront signed cookies node,js
The cookies should have 3 keys and their values:
CloudFront-Expires
CloudFront-Signature
CloudFront-Key-Pair-Id
You also need to add cookie/key CloudFront-Key-Pair-Id= APKAIQSVJ2R3T6PYTOUQ when making the request.
The CloudFront-Key-Pair-Id is not the public key, it just the ID(like an access key ID) so CloudFront can see which public key it needs to decrypt the signature. You can have up to 2 keys active on CloudFront and you create the signature with private key and Public key is with CloudFront, when cloudfront receives the request, it checks the CloudFront-Key-Pair-Id to know which public it should use, so end of story, the CloudFront-Key-Pair-Id is the ID when you login to AWS console and go to Security Credentials and click CloudFront Keypairs, You'll see a Access Key ID, thats one you need to define. (which is same as the file name)

I want to consume login API (node.js) on my swift code using Alamofire

Im getting an error while im trying to login:
there's my login service, im sure it works so well because I tested it on postman, and I worked with it already on android, and it works perfectly, encrypted password and salt works so well ..
app.post('/login/',(req,res,next)=>{
var post_data = req.body;
//Extract email and password from request
var user_password = post_data.password;
var email = post_data.email;
con.query('SELECT * FROM user where email=?',[email],function (err,result,fields) {
con.on('error', function (err) {
console.log('[MYSQL ERROR]', err);
});
if (result && result.length)
{
var salt = result[0].salt;
var encrypted_password = result[0].encrypted_password;
var hashed_password = checkHashPassword(user_password, salt).passwordHash;
if (encrypted_password == hashed_password)
res.end(JSON.stringify(result[0]))
else
res.end(JSON.stringify('Wrong Password'))
}
else {
res.json('user not exists!!');
}
});
})
and there's my swift code on btn_login action, im using Alamofire, he shows me an error with the url, but i worked with same url on displaying data from my table at it worked fine
#IBAction func btn_login(_ sender: Any) {
let serverUrl = "https://127.0.0.1:1337/login"
guard let email = emailtf.text, !email.isEmpty else {return}
guard let password = passwordtf.text, !password.isEmpty else {return}
let loginRequest = [
"email" : email,
"password" : password
]
Alamofire.request(serverUrl, method: .post, parameters: loginRequest, encoding: JSONEncoding.default, headers: nil)
.validate(statusCode:200..<300)
.responseJSON { response in
switch response.result {
case .success(let value):
print(value)
break
case .failure(let error):
print(error)
break
}
}
}
and im getting this error on xcode console
["Email": "test", "Password": "test"]
2019-11-23 15:41:19.991572+0100 ProjetIOS[19982:799169] Task <F5DB6B8F-2658-4C83-BF64-663B04673CAC>.<1> finished with error [-1002] Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL" UserInfo={NSLocalizedDescription=unsupported URL, NSErrorFailingURLStringKey=localhost:1337/login, NSErrorFailingURLKey=localhost:1337/login, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <F5DB6B8F-2658-4C83-BF64-663B04673CAC>.<1>"
), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <F5DB6B8F-2658-4C83-BF64-663B04673CAC>.<1>, NSUnderlyingError=0x600002f809f0 {Error Domain=kCFErrorDomainCFNetwork Code=-1002 "(null)"}}
Request failed with error: Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL" UserInfo={NSLocalizedDescription=unsupported URL, NSErrorFailingURLStringKey=localhost:1337/login, NSErrorFailingURLKey=localhost:1337/login, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <F5DB6B8F-2658-4C83-BF64-663B04673CAC>.<1>"
), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <F5DB6B8F-2658-4C83-BF64-663B04673CAC>.<1>, NSUnderlyingError=0x600002f809f0 {Error Domain=kCFErrorDomainCFNetwork Code=-1002 "(null)"}}
Any help please? Thank you
put your local IP instead of localhost in url .
e.g. http://192.168.1.34:1337/
Also try adding headers in your Alamofire request. Here is an example:
let loginRequest = [
"Email" : self.emailtf.text! as String,
"Password" : self.passwordtf.text! as String
]
let headers = ["Content-Type" : "application/json"]
Alamofire.request(url, method : .post, parameters : loginRequest, encoding :
JSONEncoding.default , headers : headers).responseData { dataResponse in
print(dataResponse.request as Any) // your request
print(dataResponse.response as Any) // your response
}

ServiceStack Cookie not setting in browser

I have an application with Razor Enabled and a service like this:
public object Post(SelectTerminalRequest request)
{
var location = base.Request.AbsoluteUri.CombineWith(request.TerminalId, "/flights");
if (Request.Cookies.ContainsKey("Terminal"))
{
Request.Cookies.Remove("Terminal");
}
Request.Cookies.Add("Terminal",
new Cookie("Terminal", request.TerminalId.ToString())
{ Expires = DateTime.Now.AddYears(1) });
return new HttpResult(HttpStatusCode.Redirect)
{
Location = location
};
}
However, when I try and access that cookie in my Razor View, its empty:
#{
Cookie cookie;
Request.Cookies.TryGetValue("Terminal", out cookie);
var baseUri = Request.GetApplicationUrl() + "/terminals";
var redirectUrl = cookie != null ? baseUri + "/" + cookie.Value + "/flights" : baseUri;
}
When I browse my cookies, I don't see anything with Terminal:
You'll kick yourself for this one, I am sure, but adding cookies should be on the Response, you used the Request object. :) Don't worry I've done that too!
Response.SetCookie("Terminal", request.TerminalId.ToString());

Possible to get username of HTTP auth logged user by Google Chrome Extension?

Please, is it possible to get username of HTTP auth logged user by Google Chrome Extension? Permissions aren't problem, I can set all of them.
Thank you!
http://code.google.com/chrome/extensions/devguide.html
You can use the webRequest API to look at headers for you. Here's some sample code the parses out the base64-encoded username and password from the Authorization header of all HTTP requests:
chrome.webRequest.onSendHeaders.addListener(function(details) {
console.log(details.url, details.requestHeaders);
for(var i = 0; i < details.requestHeaders.length; ++i) {
var header = details.requestHeaders[i];
if(header.name == "Authorization") {
// this is my quick effort for parsing the auth value
// formatted like "Basic [base64 of 'user:pass']"
var b64val = header.value.split(" ")[1];
var credArray = atob(b64val).split(":");
var user = credArray[0];
var pass = credArray[1];
// now do something with user/pass
}
}
},
{"urls":["*://*/*"]},
["requestHeaders"]);

Resources