When using temporary sessions it works fine. Log into the auth service and calling /auth without any parameters and it shows the display name, session id, etc.
When I log in with RememberMe=true, that call returns the session information properly. But on subsequent calls to /auth without any parameters, ServiceStack returns a 401 not authenticated. The session object's IsAuthenticated property is true and actually exists. My code checks for this and if it's false, forwards the user to the login page which doesn't happen so I know the user really is authenticated.
I am not doing anything different. How can I authenticate with a permanent session and get subsequent calls to /auth to acknowledge that I am logged in?
If it helps I'm using a CustomCredentialsProvider.
Update:
AppHost code:
public override void Configure(Funq.Container container)
{
//Set JSON web services to return idiomatic JSON camelCase properties
ServiceStack.Text.JsConfig.EmitCamelCaseNames = true;
Config.RestrictAllCookiesToDomain = ConfigurationManager.AppSettings["cookieDomain"];
Plugins.Add(new AuthFeature(() => new CustomUserSession(),
new IAuthProvider[] {
new CustomCredentialsProvider()
{ SessionExpiry =
TimeSpan.FromMinutes(Convert.ToDouble(ConfigurationManager.AppSettings["SessionTimeout"]))
},
}) //end IAuthProvider
{
IncludeAssignRoleServices = false,
IncludeRegistrationService = false,
HtmlRedirect = ConfigurationManager.AppSettings["mainSiteLink"] + "Login.aspx"
} //end AuthFeature initializers
);//end plugins.add AuthFeature
Plugins.Add(new PostmanFeature() { EnableSessionExport = true });// this is only for when we want the feature and it's NOT in DebugMode
Plugins.Add(new SwaggerFeature());
Plugins.Add(new CorsFeature(allowedOrigins: "*",
allowedMethods: "GET, POST, PUT, DELETE, OPTIONS",
allowedHeaders: "Content-Type, Authorization, Accept",
allowCredentials: true));
container.Register<IRedisClientsManager>
(c => new PooledRedisClientManager(2, ConfigurationManager.AppSettings["redisIpPort"]));
container.Register<ICacheClient>(c => c.Resolve<IRedisClientsManager>().GetCacheClient());
container.Register<ISessionFactory>(c => new SessionFactory(c.Resolve<ICacheClient>()));
var userRep = new InMemoryAuthRepository();
container.Register<IUserAuthRepository>(userRep);
//Set MVC to use the same Funq IOC as ServiceStack
ControllerBuilder.Current.SetControllerFactory(new FunqControllerFactory(container));
#if DEBUG
Config.DebugMode = true;
typeof(Authenticate).AddAttributes
(
new RestrictAttribute
(RequestAttributes.HttpGet | RequestAttributes.HttpPost)
);
#else
typeof(Authenticate).AddAttributes(new RestrictAttribute(RequestAttributes.HttpPost));
#endif
RegisterTypedRequestFilter<Authenticate>((req, res, dto) =>
{
if (dto.UserName != null && dto.UserName != string.Empty
&& dto.Password != null && dto.Password != string.Empty)
if(dto.RememberMe == null)
dto.RememberMe = false;
});
RegisterTypedResponseFilter<AuthenticateResponse>((req, res, dto) =>
{
var appSettings = new ServiceStack.Configuration.AppSettings();
dto.UserId = AppHostBase.Instance.TryResolve<ICacheClient>().SessionAs<CustomUserSession>().UserId.ToString();
dto.Meta = new Dictionary<string, string>();
dto.Meta.Add("ExpiresMinutes", appSettings.Get("SessionTimeout"));
});
}
public static void Start()
{
Licensing.RegisterLicense(licenceKey);
new ServiceStackAppHost().Init();
}
Initial request headers:
https://****.com/api2/auth?username=user&password=passwordmberme=true
GET /api2/auth?username=user&password=password&rememberme=true HTTP/1.1
Accept: text/html, application/xhtml+xml, /
Accept-Language: en-US
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: propel.zola360.com
DNT: 1
Connection: Keep-Alive
Cookie: ss-pid=P2hslABCmSs7pomRqNz5; ss-opt=perm; X-UAId=
Initial response headers:
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
X-Powered-By: ServiceStack/4.033 Win32NT/.NET
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, Accept
Access-Control-Allow-Credentials: true
X-AspNet-Version: 4.0.30319
Set-Cookie: ss-id=pojZkNAdMcEcACDREcRM; domain=.zola360.com; path=/; HttpOnly
Set-Cookie: ss-opt=perm; domain=.zola360.com; expires=Mon, 13-Nov-2034 16:11:09 GMT; - path=/; HttpOnly
Set-Cookie: X-UAId=; domain=.zola360.com; expires=Mon, 13-Nov-2034 16:11:09 GMT; path=/; HttpOnly
Set-Cookie: 47=0; domain=.zola360.com; path=/
Set-Cookie: UserId=47; domain=.zola360.com; path=/
X-Powered-By: ASP.NET
Date: Thu, 13 Nov 2014 16:11:09 GMT
Content-Length: 4129
Initial response body:
{"userId":"47","sessionId":"PKrITmRawxAtnaABCDgN","userName":"user","responseStatus":{},"meta":{"ExpiresMinutes":"360"}}
Subsequent call to /auth request:
GET /api2/auth HTTP/1.1
Accept: text/html, application/xhtml+xml, /
Accept-Language: en-US
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: propel.zola360.com
DNT: 1
Connection: Keep-Alive
Cookie: ss-pid=cvgslABCmSs6pomYdLu0; ss-opt=perm; X-UAId=; ss-id=lYWZkFAdMcZcABCDcRM; 47=0; UserId=47
Subsequent call to /auth response
HTTP/1.1 401 Not Authenticated
Cache-Control: private
Content-Type: text/html
Vary: Accept
Server: Microsoft-IIS/7.5
X-Powered-By: ServiceStack/4.033 Win32NT/.NET
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, Accept
Access-Control-Allow-Credentials: true
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 13 Nov 2014 16:11:23 GMT
Content-Length: 9731
Subsequent call to /auth body:
{"responseStatus":{"errorCode":"Not Authenticated","message":"Not Authenticated","stackTrace":"[Authenticate: 11/13/2014 3:27:49 PM]:\n[REQUEST: {}]\nServiceStack.HttpError: Not Authenticated\r\n at ServiceStack.Auth.AuthenticateService.Post(Authenticate request)\r\n at lambda_method(Closure , Object , Object )\r\n at ServiceStack.Host.ServiceRunner`1.Execute(IRequest request, Object instance, TRequest requestDto)","errors":[]}}
Update
I crafted a small Python3 script to authenticate myself and call some other web service. After authentication using RememberMe=true, the cookies come back as expected: ss-id/pid are set fine and ss-opt=perm. I figured I would print the header cookie and just paste it into a header of another request to call a different service marked with [Authenticate]. It didn't work. So I tried something silly and pasted the ss-pid cookie value into the ss-id one. It worked.
Here's the failing cookie string (session redacted :)):
cookie = "ss-id=ss-ID-session-cookie; domain=.zola360.com; path=/; HttpOnly, ss- pid=ss-PID-session-cookie; domain=.zola360.com; expires=Tue, 14-Nov-2034 01:34:25 GMT; path=/; HttpOnly, ss-opt=perm; domain=.zola360.com; expires=Tue, 14-Nov-2034 01:34:25 GMT; path=/; HttpOnly, X-UAId=; domain=.zola360.com; expires=Tue, 14-Nov-2034 01:34:25 GMT; path=/; HttpOnly, 47=0; domain=.zola360.com; path=/, UserId=47; domain=.zola360.com; path=/"
And simply pasting the ss-pid value into ss-id works:
cookie = "ss-id=ss-PID-session-cookie; domain=.zola360.com; path=/; HttpOnly, ss- pid=ss-PID-session-cookie; domain=.zola360.com; expires=Tue, 14-Nov-2034 01:34:25 GMT; path=/; HttpOnly, ss-opt=perm; domain=.zola360.com; expires=Tue, 14-Nov-2034 01:34:25 GMT; path=/; HttpOnly, X-UAId=; domain=.zola360.com; expires=Tue, 14-Nov-2034 01:34:25 GMT; path=/; HttpOnly, 47=0; domain=.zola360.com; path=/, UserId=47; domain=.zola360.com; path=/"
And the Python3 script I used:
import httplib2 as http
import json
try:
from urlparse import urlparse
except ImportError:
from urllib.parse import urlparse
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json; charset=UTF-8'
}
uri = 'https://mysite.com'
path = '/api2/auth/credentials'
target = urlparse(uri+path)
method = 'POST'
body = '{"username": "username", "password": "password", "RememberMe": "true"}'.encode()
h = http.Http()
response, content = h.request(target.geturl(), method, body, headers)
#save the cookie and use it for subsequent requests
cookie = response['set-cookie']
print(cookie)
path2 = '/api2/time/start'
target2 = urlparse(uri+path2)
headers['cookie'] = cookie
response, content = h.request(target2.geturl(), 'GET', body, headers)
# assume that content is a json reply
# parse content with the json module
data = json.loads(content.decode())
print(data)
It seems that something still looks at the value of ss-id even if ss-opt=perm.
When Authenticating with GET /api2/auth?username=user&password=... it is sent with your permanent cookie ss-pid, i.e:
Cookie: ss-pid=P2hslABCmSs7pomRqNz5; ss-opt=perm; X-UAId=
The rememberme=true option tells ServiceStack to maintain the users session against the permanent ss-pid cookie. This option is maintained in the users ss-opt=perm cookie, which the HTTP Response tells the client to add with:
Set-Cookie: ss-opt=perm; domain=.zola360.com; expires=Mon, 13-Nov-2034 16:11:09 GMT; - path=/; HttpOnly
Although not important in this case, since the temporary session ss-id was missing from the Request, ServiceStack tells the client to add a new one with:
Set-Cookie: ss-id=pojZkNAdMcEcACDREcRM; domain=.zola360.com; path=/; HttpOnly
The issue is with the subsequent request to GET /api2/auth where the client is not re-sending the ss-pid cookie it originally authenticated with (i.e. P2hslABCmSs7pomRqNz5 vs cvgslABCmSs6pomYdLu0):
Cookie: ss-pid=cvgslABCmSs6pomYdLu0; ss-opt=perm; X-UAId=; ss-id=lYWZkFAdMcZcABCDcRM; 47=0; UserId=47
Which ServiceStack doesn't know about (i.e. doesn't maintain any session against) which is why it returns with a 401 Not Authenticated as expected.
HTTP Client should be configured to resend Cookies
It's not clear what HTTP Client you're using but it should be configured to re-send cookies which is normally the default behavior. Ajax will send both the permanent ss-pid cookies and the temporary ss-id only for that browser session, e.g. the temporary ss-id cookie will be discarded when the browser is closed and making a new request will receive a new ss-id cookie.
With the C# Service Clients, it only resends permanent cookies so the client needs to be authenticated with RememberMe = true, e.g:
var client = JsonServiceClient(BaseUrl);
var authResponse = client.Send(new Authenticate
{
provider = "credentials",
UserName = "user",
Password = "p#55word",
RememberMe = true,
});
authResponse.PrintDump();
Once Authenticated the same authenticated client instance can be used to access a protected record multiple times as seen in this Auth Test:
for (int i = 0; i < 500; i++)
{
var response = client.Send<SecureResponse>(new Secured { Name = "test" });
Console.WriteLine("loop : {0}", i);
}
Related
I am trying to publish contact group into Azure Active Directory.
Steps that I followed:
Register Application in Azure and get the Tenant ID and Client ID.
Send the CFHTTP Request for token (I need help here)
Send token and other parameters (I need help here) to publish the contact groups
cfhttp(method="POST", charset="utf-8", url="https://login.microsoftonline.com/common/oauth2/v2.0/response_type=code", result="result") {
cfhttpparam(name="Content-Type", type="header", value="application/x-www-form-urlencoded");
cfhttpparam(name="client_id", type="formfield", value="28d5e75-a762-45a2-9504-e9bbaa3294af");
cfhttpparam(name="grant_type", type="formfield", value="authorization_code");
cfhttpparam(name="mimetype", type="header", value="application/xml");
}
Response:
Header HTTP/1.1 404 Not Found Cache-Control: private Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff x-ms-request-id: caeef2f8-71a0-45f6-8820-63d880f02700 x-ms-ests-server: 2.1.10244.21 - WST ProdSlices P3P: CP="DSP CUR OTPi IND OTRi ONL FIN" Set-Cookie: x-ms-gateway-slice=prod; path=/; SameSite=None; secure; HttpOnly Date: Mon, 23 Mar 2020 18:20:59 GMT Connection: close Content-Length: 0
Mimetype Unable to determine MIME type of file.
Basically after an auth, I setting a cookie, but apparently after page refresh on the cookie that was set by cloudflare is saved
And the cookie that I transmitted with set-cookie is not used in after set-cookie requests
# Response headers
HTTP/2.0 200 OK
date: Thu, 18 Jul 2019 10:03:25 GMT
content-type: application/json; charset=utf-8
content-length: 29
set-cookie: __cfduid=d578c7a5e4378dc1b1946964a08ebc4ec1563444205; expires=Fri, 17-Jul-20 10:03:25 GMT; path=/; domain=.doc.io; HttpOnly; Secure
set-cookie: __doc=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlIjoiNzQ2NTczNzQ0MDY2NjE3Mzc0NmQ2MTY5NmMyZTZkNzgiLCJwIjoiNTUzMjQ2NzM2NDQ3NTY2YjU4MzEzODMzNTU0NjUwNTU2ZjRiMzkzMTY3NDUzNDY5NDc3MzM3MzgzOTU5MzczMDUxNjk0ZjQxNjQ0OTM5Nzg0YjZiNzU1Njc3Nzk0NDc0NjE3NDMxNTE0NzcwMzE0YjQxNmY1MjU5MzM3YTZhNDU2NDJiNmU0ZTc0NGE3NTMyNTQ1ODc2NjI1YTczNDc1MTQ1Njc0MjVhNGQ0MTNkM2QiLCJkIjoiMzEzNTM2MzMzNDM0MzQzMjMwMzUzNTM2MzMiLCJpYXQiOjE1NjM0NDQyMDV9.go1jDpc2rBe5FjK2sKX4ybW4PhCPFq1xT1WIX-mSI84; Domain=.doc.io; Path=/; Expires=Thu, 18 Jul 2019 16:03:25 GMT; HttpOnly; Secure
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
server: cloudflare
cf-ray: 4f83a02a3dc36455-FRA
X-Firefox-Spdy: h2
reply
.code(200)
.header('Access-Control-Allow-Origin', '*')
.header('Content-Type', 'application/json; charset=utf-8')
.setCookie('__doc', token, {
domain: '.doc.io',
path: '/',
secure: true,
httpOnly: true,
expires: new Date(new Date().setHours(new Date().getHours() + 6))})
.send({ 'success': 'Sign In success' })
All my websites are https
First I do POST request for an auth on /auth, and you could see response in response headers above and after I do GET on (trying to load page) from /page and get cookies, but with reply.log.info(request.cookies) I see only cookies from cloudflare. Surely I tried to refresh and go to address in different table, there just no any cookies, but from cloudflare.
# Request headers
Host: test.doc.io
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:67.0) Gecko/20100101 Firefox/67.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
DNT: 1
Connection: keep-alive
Cookie: __cfduid=d578c7a5e4378dc1b1946964a08ebc4ec1563444205
Upgrade-Insecure-Requests: 1
TE: Trailers
After I tested it with an actual page with js code for a XHR request it works fine. However cookie was only displayed, but not actually saved in the storage when I was sending request directly in Firefox's inspector. Lost a day to figure out that created in inspector cookies seems preventing from installing
Have a simple get Customer api that's returning list of customers fine.
Setting up for service to service authentication, if I make this [Authenticated] and try to implement using ApiKeyAuthProvider, the req.GetApiKey returns null and I get an error;
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 POST https://localhost:44347/api/customers application/json 0
Microsoft.AspNetCore.Hosting.Internal.WebHost:2019-07-01 16:50:34,004 [16] INFO Microsoft.AspNetCore.Hosting.Internal.WebHost - Request starting HTTP/1.1 POST https://localhost:44347/api/customers application/json 0
The thread 0x42cc has exited with code 0 (0x0).
The thread 0x302c has exited with code 0 (0x0).
ServiceStack.ServiceStackHost:2019-07-01 17:01:14,601 [16] ERROR ServiceStack.ServiceStackHost - ServiceBase<TRequest>::Service Exception
System.ArgumentOutOfRangeException: Length cannot be less than zero.
Parameter name: length
at System.String.Substring(Int32 startIndex, Int32 length)
at ServiceStack.Host.HttpRequestAuthentication.GetBasicAuth(IRequest httpReq) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\HttpRequestAuthentication.cs:line 45
at ServiceStack.Host.HttpRequestAuthentication.GetBasicAuthUserAndPassword(IRequest httpReq) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\HttpRequestAuthentication.cs:line 50
at ServiceStack.Auth.ApiKeyAuthProvider.PreAuthenticate(IRequest req, IResponse res) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Auth\ApiKeyAuthProvider.cs:line 232
at ServiceStack.AuthenticateAttribute.PreAuthenticate(IRequest req, IEnumerable`1 authProviders) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\AuthenticateAttribute.cs:line 96
at ServiceStack.AuthenticateAttribute.ExecuteAsync(IRequest req, IResponse res, Object requestDto) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\AuthenticateAttribute.cs:line 74
at ServiceStack.Host.ServiceRunner`1.ExecuteAsync(IRequest req, Object instance, TRequest requestDto) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\ServiceRunner.cs:line 127
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 640574.8754ms 400 application/json; charset=utf-8
Microsoft.AspNetCore.Hosting.Internal.WebHost:2019-07-01 17:01:14,607 [16] INFO Microsoft.AspNetCore.Hosting.Internal.WebHost - Request finished in 640574.8754ms 400 application/json; charset=utf-8
Clearly I have missed something obvious...any pointers appreciated.
// Register ORMLite connection
container.Register<IDbConnectionFactory>(dbFactory);
//Tell ServiceStack you want to persist User Auth Info in SQL Server
container.Register<IAuthRepository>(c => new OrmLiteAuthRepository(dbFactory));
// See https://docs.servicestack.net/api-key-authprovider
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new ApiKeyAuthProvider(AppSettings) {
SessionCacheDuration = TimeSpan.FromMinutes(10),
AllowInHttpParams = true, // Whether to allow API Keys in 'apikey' QueryString or FormData (e.g. `?apikey={APIKEY}`)
RequireSecureConnection = true,
},
}
) {
IncludeRegistrationService = true,
});
GlobalRequestFilters.Add((req, res, dto) =>
{
LastApiKey = req.GetApiKey();
});
Request
POST https://localhost:44347/api/customers HTTP/1.1
Host: localhost:44347
Connection: keep-alive
Content-Length: 2
Accept: application/json
Origin: https://localhost:44347
Authorization: yDOr26HsxyhpuRB3qbG07qfCmDhqutnA-yDOr26HsxyhpuRB3qbG07qfCmDhqutnA-yDOr26HsxyhpuRB3qbG07qfCmDhqutnA
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
Content-Type: application/json
Referer: https://localhost:44347/swagger-ui/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9,en-US;q=0.8
{}
Response
HTTP/1.1 400 ArgumentOutOfRangeException
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Vary: Accept,Origin
Server: Microsoft-IIS/10.0
X-Powered-By: ServiceStack/5.50 NetCore/Windows
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS
Access-Control-Allow-Headers: Content-Type
X-Startup-Errors: 1
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: Content-Disposition
X-SourceFiles: =?UTF-8?B?QzpcUmVwb3NcTUJXZWJccnZhcGlcUnZXZWJcUnZBcGlcYXBpXGN1c3RvbWVycw==?=
X-Powered-By: ASP.NET
Date: Wed, 03 Jul 2019 08:07:40 GMT
13e
{"responseStatus":{"errorCode":"ArgumentOutOfRangeException","message":"Length cannot be less than zero.\r\nParameter name: length","errors":[{"errorCode":"ArgumentOutOfRangeException","fieldName":"length","message":"Length cannot be less than zero.\r\n"}]},"responseCreatedUtcDateTime":"2019-07-03T08:07:40.7955827Z"}
0
Your client is sending an invalid Authorization Bearer Token, it needs to have the Authroization Bearer Token format:
Authorization: Bearer {Token}
If you're sending an Authenticated API Key or JWT Request via Open API it needs to have the Bearer prefix as per the Open API docs:
OK I had manually created a User and APIKey in the underlying tables and had used a UserAuthId 'SomeAuthId' i.e. letter in them, and the ORM repository code is expecting these to be integers. Its cool that I can see the code in github and debug this myself - thanks for the comment as it got me thinking and looking into my Auth setup.
I'm trying to get Fastly pointed at my heroku instance that is running hapijs and serving static files from /assets/. I have a route setup that looks like this:
// Assets
{
method: "GET",
path: "/assets/{path*}",
config: {
cache: {
privacy: 'public',
expiresIn: 31536000000 // 1 year in milliseconds
}
},
handler: {
directory: { path: './public/assets'}
}
},
Here are the headers sent back on each request:
HTTP/1.1 200 OK
content-type: text/css; charset=utf-8
last-modified: Thu, 22 Jan 2015 07:08:07 GMT
etag: "9c7d48799e5230b7c97ef1978b81ad533c10b950"
set-cookie: csrf=xyz; Path=/
set-cookie: session=xyz; Path=/
cache-control: max-age=31536000, must-revalidate, private
Date: Thu, 22 Jan 2015 07:21:15 GMT
Connection: keep-alive
How do I not set cookies on the responses from this enpoint and why does the cache-control header set must-revalidate and private. Shouldn'it just be public?
I finally solved this issue. I had a few plugins that were setting cookies: yar, hapi-auth-cookie, and crumb. Unfortunately there is not yet any standard way of removing plugins from a particular route.
crumb allows you to add a skip function to the registration options that will disable it.
auth let's you disable it at the route config by setting auth: false.
yar doesn't yet have any mechanism for doing this so I submitted a PR to fix it
You can also remove cookies via Fastly, before the response is considered to be stored in the cache. For this you need to do the following configuration steps:
Content -> Headers:
Name Remove Set-Cookie from /assets
Type: Cache
Action: Delete
Destination: http.Set-Cookie
On that newly generated Header Configuration: Settings -> Cache Conditions ->
New
Name: /assets
Apply If: req.url ~ "^/assets/"
That will remove the Set-Cookie header before it's "seen" by Fastly and will thus make it cachable.
I am trying to login into oddsportal through a VBA script. I have written the following code but it is not working. I am getting an error when I am truing to set cookie for POST request. I would be thankful if someone could point me in the right direction.
Dim WHTTP As Object
Dim myuser, mypass, url, strAuthenticate As String
Dim out As String
url = "http://www.oddsportal.com/"
myuser = "user"
mypass = "pass"
strAuthenticate = "login-username=" & myuser & "&login-password=" & mypass & "&login-submit="
Set WHTTP = CreateObject("WinHTTP.WinHTTPrequest.5.1")
WHTTP.Open "POST", url, False
WHTTP.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36"
WHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
WHTTP.setRequestHeader "Connection", "keep-alive"
WHTTP.send strAuthenticate
strCookie = WHTTP.getResponseHeader("Set-Cookie") **'I am getting an error here**
strResponse = WHTTP.ResponseText
WHTTP.Open "GET", "http://www.oddsportal.com/soccer/africa/africa-cup-of-nations/results/", False
WHTTP.setRequestHeader "Connection", "keep-alive"
WHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
WHTTP.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36"
WHTTP.setRequestHeader "Cookie", strCookie
WHTTP.send
out = WHTTP.ResponseText
I changed the authentication method to server based using setcredential method. Now I am able to set cookie from the first part. However, I am still unable to get the data from second page (second part of the code). Here are the response headers that I got using setcredentials: My set cookie line is only able to retain the last cookie.
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection: keep-alive
Date: Tue, 27 May 2014 16:01:29 GMT
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: text/html
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Age: 0
Server: Apache
Set-Cookie: op_lang=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/
Set-Cookie: op_oddsportal=fehof62734n35crjd9vpshhf10; path=/
Set-Cookie: op_cookie-test=ok; expires=Wed, 27-May-2015 16:01:28 GMT; path=/
Set-Cookie: op_state=1
Set-Cookie: op_last_id=1; expires=Thu, 26-Jun-2014 16:01:28 GMT; path=/
Set-Cookie: op_cookie-test=ok; expires=Wed, 27-May-2015 16:01:28 GMT; path=/
Vary: Accept-Encoding
X-Deliver: Tue, 27 May 2014 16:01:29 GMT
This is cookie that I get from Fiddler:
Set-Cookie:op_user_logout=0; expires=Mon, 18-May-2015 18:44:49 GMT; path=/
Set-Cookie:op_last_id=1; expires=Thu, 26-Jun-2014 18:44:49 GMT; path=/
Set-Cookie:op_user_login_id=95774; expires=Mon, 18-May-2015 18:44:49 GMT; path=/
Set-Cookie:op_user_login_hash=73a967ad18d6a353afa12877309f4708; expires=Mon, 18-May-2015 18:44:49 GMT; path=/
Set-Cookie:op_cookie-test=ok; expires=Wed, 27-May-2015 18:44:48 GMT; path=/
Set-Cookie:op_user_time_zone=1.00; expires=Thu, 26-Jun-2014 18:44:49 GMT; path=/
Set-Cookie:op_user_full_time_zone=35; expires=Thu, 26-Jun-2014 18:44:49 GMT; path=/
Set-Cookie:op_lang=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/
I'm not sure it will help in this specific case, but request and response cookies handling is included in my library Excel-REST. Here's an example of getting and setting the login id and hash:
Dim OddsClient As New RestClient
OddsClient.BaseUrl = "http://www.oddsportal.com/"
Dim LoginRequest As New RestRequest
LoginRequest.Method = httpPOST
LoginRequest.Format = formurlencoded
LoginRequest.AddParameter "login-username", myuser
LoginRequest.AddParameter "login-password", mypass
LoginRequest.AddParameter "login-submit", ""
Dim LoginResponse As RestResponse
Set LoginResponse = OddsClient.Execute(LoginRequest)
If LoginResponse.StatusCode = 200 Then
Dim OddsRequest As New RestRequest
OddsRequest.Resource = "soccer/africa/africa-cup-of-nations/results/"
OddsRequest.AddCookie "op_user_login_id", LoginResponse.Cookies("op_user_login_id")
OddsRequest.AddCookie "op_user_login_hash", LoginResponse.Cookies("op_user_login_hash")
Dim OddsResponse As RestResponse
Set OddsResponse = OddsClient.Execute(OddsRequest)
End If
I had some difficulty retrieving cookies from headers, since every cookie has the same header key, "Set-Cookie". In Excel-REST I split getAllResponseHeaders into a Collection of key-value headers for ease of access and then pulled out those with the "Set-Cookie" key (See RestHelpers). For your example, something similar to the following may work:
Dim Headers As Collection ' of Dictionaries with key, value
Set Headers = ExtractHeadersFromResponseHeaders(WHTTP.getAllResponseHeaders) ' from RestHelpers
' Setup GET...
Dim Header As Dictionary
For Each Header In Headers
' Move all cookies from login to GET request
If Header("key") = "Set-Cookie" Then
WHTTP.setRequestHeader "Cookie", Header("value")
End If
Next Header