Kibana authentication when sharing the dashboard in web application

Hi,
cluster ID : cd59e4

want to show kibana dashboard in my webapplication.
on opening kibana it is asking for authentication .
I dont want my user to enter credentials again .
and anonymous user is not secure ...

can you give me a restful api method where I can pass credentials and get session id from client browser
or a way i can generate a session id in my server and send it to client and and access kibana from client browser.

What are you using that authentication is required?

If you're using a proxy of some kind to give you Basic auth protection to Elasticsearch (which I'm guessing is why Kibana is asking for login details), you could use another proxy between the user and Kibana that would inject the Basic authorization header into the request, so the end user wouldn't need to do anything.

Note that removing that authentication step from the user is going to reduce the security of the system significantly, but I'm guessing you're probably already away of that...

sorry forgot to mention that we are hosting our data in elastic cloud
and kibana also from elastic cloud,
and i want to share a dashboard in .Net MVC web application which have its own login and sessions.

when we open the kibana containing page it is asking for credentials.
passing credentials in url didnot work.

can you tell me a way where i can include kibana dashboard in a page without user entering credentials.

OK, so then security is provided via Shield, at least as far as I understand it. Which I believe means that your users are greeted with a dark-colored login form, as opposed to a Basic auth thing, when trying to access the Kibana visualizations.

Unfortunately, that login method doesn't work with Basic auth in the current versions of the software (Kibana 4.4 and Elasticsearch 2.2), and uses an encrypted cookie to handle authentication, so the only way you can apply it automatically is to generate the cookie yourself and somehow inject it into the user's session for your Kibana domain. It's definitely not trivial to pull off, and as far as I know, there's no alternative.

The next release of the stack (Kibana 4.5 and Elasticsearch 2.3) brings back Basic auth, which means that you simply need to pass Basic credentials via the Authorization header and it'll create that cookie transparently for you. This is easier, as you don't need to handle the encryption bit yourself, but you still have to inject that header into the user's session.

Those are the only ways I can think to pull off what you're trying to do. And the only way I can think to inject information into the user's session is via some external proxy, which you'd have to operate outside of Cloud.

I'd recommend bringing this up in the Cloud thread though, maybe there's another way to do this that I'm not thinking about.

Thanks for the info .
yes security is provided by shield.
but we are not getting any dark colored authentication form . it is a login alert box from browser.

Oh, then the Kibana instance must not be using the Shield plugin. If you're getting the generic browser login, then all you need to do is add the Basic auth headers to the request. I believe you'd still need to proxy the requests, which you could build into your custom application.

The basic idea is that instead of linking the iframe directly to the Kibana panels, you would link them to your application, which would pass the request on to the Kibana instance, injecting the required Authorization headers into that request. Then the end user would never get prompted for a login besides the one in your application.

yes injected the basic auth in the request . but is showing an error

response for preflight is invalid http status code 401

in firebug of chrome

401 is not authorized, so I suspect the headers are either not being injected or the wrong thing is being sent. What output do you see from the Elasticsearch logs when you try to make a request with the headers injected?

I have this kibana page as response from the url
when i make a request without credentials.

Kibana 4
<div class="col-md-offset-4 col-md-4 page-header initial-load">
  <center>
    <img width="128" alt="Loading Kibana" src="images/initial_load.gif">
    <h1>
      <strong>Kibana</strong>
      <small id="cache-message">is loading. Give me a moment here. I'm loading a whole bunch of code. Don't worry, all this good stuff will be cached up for next time!</small>
    </h1>
  </center>
</div>

<script>
  window.KIBANA_VERSION='4.1.4';
  window.KIBANA_BUILD_NUM='7616';
  window.KIBANA_COMMIT_SHA='3df681b3f205b2b75e11ddf68c0985f80460d7bc';
</script>

<script src="bower_components/requirejs/require.js?_b=7616"></script>
<script src="require.config.js?_b=7616"></script>
<script>
  var showCacheMessage = location.href.indexOf('?embed') < 0 && location.href.indexOf('&embed') < 0;
  if (!showCacheMessage) document.getElementById('cache-message').style.display = 'none';

  if (window.KIBANA_BUILD_NUM.substr(0, 2) !== '@@') {
    // only cache bust if this is really the build number
    require.config({ urlArgs: '_b=' + window.KIBANA_BUILD_NUM });
  }

  require(['kibana'], function (kibana) { kibana.init(); });
</script>

and then it is poping up for login after loding all the js.

Hey . I am trying to load the Kibana Dashboard in iframe. I am using shield which kibana. For enabling session, I have made /api/security/v1/login api call using ajax with following credentials:

{
"password": "YOURPASSWORD",
"username": "YOURUSERNAME"
}
and kbn-version: 5.1.1 in header

I got the success response. But after getting the success response, When I try to load any another route like reply.redirect('/app/kibana') It gives the unauthorized error(401). I think the session is not passed to kibana route. Do you have any idea how to redirect to kibana route once the login api is called using ajax.

I want to load Dashbaord in my another application using iframe. That's why I made ajax request from my application.

The response just sets a cookie, which should be read and verified on subsequent requests.

How are you doing the initial login request, in the iframe, or in the app that's loading the iframe? If Kibana is running on another hostname or port, the cookie isn't going to be valid.

Can you describe the entire flow of the application here? And also, are you getting any kind of message with the 401 error?

@Joe_Fleming Thanks for your reply. I have figured out the issue. There is some issue while posting the data through iframe. It's working fine now.

@hardik.rapidops

We are also facing cross origin issue making the request to /api/security/v1/login. Can you please share the work around for this.

@PrabakarKaruppasamy For enabling support for cross origin, You need to do some changes in kibana/src/server/http/setup_connection.js file. You need to change cors property in connectionOptions. I have changed it something like below:

const connectionOptions = {
    host,
    port,
    state: {
      strictHeader: false
    },
    routes: {
      cors: {
        additionalHeaders: ['kbn-version','cookie'],
        origin: ['*']
      },
      payload: {
        maxBytes: config.get('server.maxPayloadBytes')
      }
    }
  };

You can also pass it via config file. It's simple cors which will be provided by HAPI. You can also enable cors for specific route only for login. I have added it globally because I want to use it in other routes also. You can add it in route config. Let me know If it makes any sense.

@hardik.rapidops https://discuss.elastic.co/u/hardik.rapidops

It makes sense. Nice one.. It is resolved the cross origin issue..But the
cookies not getting stored in the browser.. We can able to see in the
response. We can't able to manipulate the cookies.

@PrabakarKaruppasamy

If you are making ajax request then it might be creating issues for storing cookies in browser. If you can just post the simple form without doing ajax then browser will store the cookie.

@hardik.rapidops

we are trying to make the silent login to Kibana (without getting loginid/password from user, not showing the login page). can we post the form for this case.
Is there any way can we disable httpOnly flag to false.. Is it make sense?

@PrabakarKaruppasamy

I am not sure about httpOnly flag. But using javascript, suppose you have one html page and whenever you want to visit that page, you want to do silent login. That page doesn't contain any username and password field, but whenever you will visit that html page, using javascript onload function, you can submit the form. You just need to pass username and password like input type="hidden" value="<your username>" and you need to place this input tags inside form. When your page is loaded it will automatically submit the form your session and cookie will be stored. Let me know If it makes any sense.

@hardik.rapidops

We have tried like below
In html

form method="POST" name="silentForm" action="http://x.x.x.x:8100/api/security/v1/login" >
input type="hidden" name="kbn-version" id="kbn-version" value="x.x.x" />
input type="hidden" name="username" id="username" value="xyz" />
input type="hidden" name="password" id="password" value="abcd" />
form

In Javascript

        window.onload = function(){
            alert('window on load called');
            document.forms['silentForm'].submit();
            alert('form submited');
        }

But we got the error message is {"statusCode":400,"error":"Bad Request","message":"Request must contain an kbn-xsrf header"}

@PrabakarKaruppasamy

You are getting this error becuse in kibana whenever we make any api request we need to pass kbn-version as a header and kbn-version will be main package.json version. But in your situation we can't pass header through simple form post. So you need to bypass checking of kbn-xsrf header in following kibana/src/server/http/xsrf.js

import { badRequest } from 'boom';

export default function (kbnServer, server, config) {
const disabled = config.get('server.xsrf.disableProtection');
const versionHeader = 'kbn-version';
const xsrfHeader = 'kbn-xsrf';

server.ext('onPostAuth', function (req, reply) {
if (disabled) {
return reply.continue();
}

const isSafeMethod = req.method === 'get' || req.method === 'head';
const hasVersionHeader = versionHeader in req.headers;
const hasXsrfHeader = xsrfHeader in req.headers;
// if (!isSafeMethod && !hasVersionHeader && !hasXsrfHeader) {
//   return reply(badRequest(`Request must contain an ${xsrfHeader} header`));
// }
return reply.continue();

});
}

In above code I have just commented out if condition which is checking of header. After doing this, I don't think so you will face any issues. Let me know If you are still facing any issues.