Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cookie authentication #36

Closed
jozzhart opened this issue Jul 24, 2013 · 17 comments
Closed

Cookie authentication #36

jozzhart opened this issue Jul 24, 2013 · 17 comments

Comments

@jozzhart
Copy link

I see it's possible to authenticate using OAUTH by making subsequent calls after making the OAUTH call, but is there a way to get the returned cookie from a login POST and then add it to the header?

@cboden
Copy link
Contributor

cboden commented Jul 24, 2013

From my experience Frisby passes cookies on to subsequent requests automatically.

@jozzhart
Copy link
Author

I am able to get my tests to pass if I manually set the header cookie to a value that I generate via the browser.

But I get Unauthorized if I do not manually assign a cookie session value.

@jozzhart jozzhart reopened this Jul 24, 2013
@cboden
Copy link
Contributor

cboden commented Jul 24, 2013

Are you nesting your tests?

frisby.create('le Test')
    .post('loginUrl', {user: 'hello', pass: 'world'})
    .after(function() {
        frisby.create('Test private url')
            .get('privateUrl')
            .expectStatus(200)
        .toss()
    })
.toss()

@jozzhart
Copy link
Author

Certainly am.

frisby.create('POST Login as admin')
  .post(URL +'api/login', { username: 'xxxxxx', password: 'xxxxxx', eventId: 11})
  .afterJSON(function(response) {

    frisby.create('Get schools')
    .get(URL +'api/schools')
    .expectJSONTypes('*', {
      name: String,
      coordinator: Object,
      principal: Object,
      user: Object
    })
    .toss();
  })
.toss();

@jozzhart
Copy link
Author

Just found the .afterJSON also passes the actual NodeJS response object, after the body, i.e. .afterJSON(function(body, res) {}); Looking through that I can see the cookie is being passed back:

headers:
{ 'x-powered-by': 'Express',
  pragma: 'no-cache',
  expires: '0',
  'cache-control': 'no-cache, no-store, must-revalidate',
  'content-type': 'application/json; charset=utf-8',
  'content-length': '275',
  'set-cookie': [ 'connect.sid=s%3Am15drFwJIJtwg1Zw5_s8LMXX.ZLCcnJHHSraMemvbpsmjDjb7N2z9ytdGd27DNsN1XoM; Path=/; HttpOnly' ],
  date: 'Wed, 24 Jul 2013 15:44:41 GMT',
  connection: 'keep-alive' 
},

@vlucas
Copy link
Owner

vlucas commented Jul 24, 2013

You just need to set the header manually when you perform the next request using addHeader. Something like this:

frisby.create('POST Login as admin')
  .post(URL +'api/login', { username: 'xxxxxx', password: 'xxxxxx', eventId: 11})
  .afterJSON(function(response, res) {

    frisby.create('Get schools')
    .get(URL +'api/schools')
    .addHeader('Set-Cookie', res.headers['set-cookie'])
    .expectJSONTypes('*', {
      name: String,
      coordinator: Object,
      principal: Object,
      user: Object
    })
    .toss();
  })
.toss();

@vlucas
Copy link
Owner

vlucas commented Jul 24, 2013

Also note that, in general, APIs should be stateless, so they really shouldn't be setting cookies (most API integrations don't store and re-send cookie headers). If you're using OAuth, you should only have to send an access_token parameter with each subsequent response. It's a bit like a session id, only it doesn't involve headers.

@jozzhart
Copy link
Author

Thanks Vlucas & cboden, got it to work using this.

frisby.create('POST Login as admin')
  .post(URL +'api/login', { username: 'xxxxxxxx', password: 'xxxxxxxx', eventId: 11})
  .after(function(body, res) {

    //  Grab returned session cookie
    var cookie = res.headers['set-cookie'][0].split(';')[0];

    frisby.create('Get school details')
    //  Pass session cookie with each request
    .addHeader('Cookie', cookie)
    .get(URL +'api/school')
    .expectJSONTypes({
      name: String,
      coordinator: Object,
      principal: Object,
      user: Object
    })
    .toss();
  })
.toss();

@jozzhart
Copy link
Author

I agree Vlucas, a true RESTful api should be stateless, and use OAUTH or similar to manage authentication.

@AoDev
Copy link

AoDev commented Jul 26, 2013

Just wanted to share my solution if someone else comes here.I had the same problem.
In my case, the cookie sent by the server is a 3 elements array in res.headers['set-cookie'].

So I did the following:

var setCookie = res.headers['set-cookie']
var cookie = ''

if (Array.isArray(setCookie)) {
    for (var i = 0, len = setCookie.length; i < len; i++) {
        cookie += setCookie[i].split(';')[0]
        if (i < len - 1)
            cookie += '; '
    }
}

@mostly-novice
Copy link

thank you thank you guys!!

@jozzhart - this line: .addHeader('Cookie', cookie) really helped me out.

@JesusLopezCh
Copy link

Really really helpful!

Thanks 💃

@nuno-innoflair
Copy link

Exactly what I was looking for! Thx!

@Jjarrard
Copy link

same with mostly-novice ".addHeader('Cookie', cookie)" saved my life.

@ghost
Copy link

ghost commented May 6, 2016

can the get request be used with the .addHeader('xxx', xxx) command?

@vlucas
Copy link
Owner

vlucas commented May 7, 2016

@bradleywhit Yes, of course - and it is in the code above.

@grtjn
Copy link

grtjn commented Nov 26, 2018

It looks like the frisby api changed a bit in the past couple of years. For posterity, I did it just now using:

    return frisby.fetch(loginUrl, {
      method: 'POST',
      body: JSON.stringify({
        username: 'myuser',
        password: 'mypass'
      }),
      credentials: 'same-origin'
    })
       ...
      .then(function(res) {
        return frisby.fetch(statusUrl, {
          method: 'GET',
          headers: {
            cookie: res.headers.get('set-cookie')
          },
          credentials: 'same-origin'
        })
          ...;
      });
  });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants