LinOTP API - I can´t create token using him !

780 views
Skip to first unread message

mca...@gmail.com

unread,
Apr 8, 2015, 9:34:46 AM4/8/15
to lin...@googlegroups.com
Hi.

I was some tests with linOTP using the API offer. But any function that I use (except the authentication function) the JSON return -311 error: you have not session valid.

I not found many examples to how implement this API, anybody can help me ?

Thanks any help.

Marcelo.

Kay Winkler

unread,
Apr 8, 2015, 11:17:42 AM4/8/15
to lin...@googlegroups.com
Hi Marcello,

the admin calls require to have a session cookie and session parameter
around
thus before doing any admin call you have to subit the admin/getsession
request,
which returns a session token. on any proceeding system or admin call
this session
has to be put in the cookie header and in the request parameter list.

I append you an example python script which does an mass enroll of sms
tokens
- querying your user base and enroll an sms token for those who have a
mobile number

Of cause, as well you can use wget and bash script to get the session -
thoung I have
currently no script for you.

the 3.rd option is though to use our linotp adminclient ;-)


The interssting part for the new version 2.7.2 is that we provide as
well an userservice api
where a user can enroll himself a token, but as well: there is currently
no example :-(

Best regards,

Kay
--
Kay Winkler (Software Development) <Kay.W...@lsexperts.de>
Mobil: +49 1751 874 258, Phone: +49 6151 860 86 262, Fax: 299

LSE Leading Security Experts GmbH, Postfach 100121, 64201 Darmstadt
Geschäftsführer: Oliver Michel, Sven Walther, http://www.lsexperts.de
Unternehmenssitz: Weiterstadt, Amtsgericht Darmstadt: HRB8649

linotp-enroll-smstokens
Kay_Winkler.vcf

Marcelo Cruz Ribeiro

unread,
Apr 9, 2015, 1:22:16 PM4/9/15
to lin...@googlegroups.com, Kay.W...@lsexperts.de, kay.w...@lsexperts.de
 Hi Kay.

If possible, a simple example of a enroll token throught LinOTP API ? I don´t understand that how I make to send for the admin/init the session cookie, I try take the cookie but I can´t.

Help me please !

Thanks

Marcelo

Kay Winkler

unread,
Apr 9, 2015, 1:30:19 PM4/9/15
to lin...@googlegroups.com
Dar Marcelo,

in the python code there are most of your questions explained.

But lets go one step back - and lets clarify
- what do you want to achieve?
- what is the programming scope (programming language++)?

I will ask my collegue for the simple bash script.

Or do you want to make a test in your browser only?

Best regards,

    Kay
--
You received this message because you are subscribed to the Google Groups "LinOTP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linotp+un...@googlegroups.com.
Visit this group at http://groups.google.com/group/linotp.
To view this discussion on the web visit https://groups.google.com/d/msgid/linotp/93fe3f17-bbfa-4170-8418-dca6686f8fb5%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Kay_Winkler.vcf

Marcelo Cruz Ribeiro

unread,
Apr 9, 2015, 2:53:23 PM4/9/15
to lin...@googlegroups.com, Kay.W...@lsexperts.de, kay.w...@lsexperts.de
I'm coding in PHP, the only thing that I need is a PHP example to enroll token.

Thanks.

Marcelo.

Kay Winkler

unread,
Apr 9, 2015, 4:56:22 PM4/9/15
to lin...@googlegroups.com
Dear Marcelo,

I'm not an expert on php so you could probable help me and provide me
your current example and I will show you the relevant parts to add -
thin, this could be the fastest way to success.

Awaiting your code snippet and best regards,

    Kay

For more options, visit https://groups.google.com/d/optout.
Kay_Winkler.vcf

Marcelo Cruz Ribeiro

unread,
Apr 10, 2015, 8:48:37 AM4/10/15
to lin...@googlegroups.com, Kay.W...@lsexperts.de, kay.w...@lsexperts.de
Ok Kay.

Here is my code:

<?php
  function geraString(){
    $lut = array(0 => "A",       1 => "B",
                 2 => "C",       3 => "D",
                 4 => "E",       5 => "F",
                 6 => "G",       7 => "H",
                 8 => "I",       9 => "J",
                 10 => "K",      11 => "L",
                 12 => "M",      13 => "N",
                 14 => "O",      15 => "P",
                 16 => "Q",      17 => "R",
                 18 => "S",      19 => "T",
                 20 => "U",      21 => "V",
                 22 => "W",      23 => "X",
                 24 => "Y",      25 => "Z",
                 26 => "2",      27 => "3",
                 28 => "4",      29 => "5",
                 30 => "6",      31 => "7"
    );

    for($x=0;$x<=20;$x++){
      $n = rand(0,31);
      $str_sentence = $str_sentence . $lut[$n];
    }
    return $str_sentence;
  }

  function linotp_init($otpkey,$serial,$user,$server){
    $ret = false;
    
    try {
      if (!function_exists("curl_init"))
        die("cURL extension is not installed!");
     
      var_dump(isset($_COOKIE["admin_session"]));
      $REQUEST="http://".$server."/admin/init?otpkey=".$otpkey."&genkey=1&keysize=20&description=&pin=&user=".$user."&realm=&type=OATH&tokenrealm=&otplen=&hashlib=sha1&session=cfe77e971185f42a33e2832dcfd150df23207270c54d4c58b895a281e6f5e20a";
      $ch=curl_init($REQUEST);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      $r=curl_exec($ch);
      curl_close($ch);

      $Object = json_decode($r);

      if (true == $Object->{'result'}->{'status'}){
         if (true == $Object->{'result'}->{'value'})
            $ret=true;
      }else{
         $ret = 'o token não foi gerado: '.$Object->{'result'}->{'error'}->{'code'}.'|'.$Object->{'result'}->{'error'}->{'message'};
      }
      
    } catch (Exception $exc) {
      echo $exc->getTraceAsString();
    }
    return $ret;
  }
  
  $str = geraString();
  $tkn_seed = hash_hmac('sha1', $str, '');
  $token = linotp_init($tkn_seed,'','seskelsen','192.168.2.66:5001');
  echo($token);
?>

Thanks.

Marcelo.

Marcelo Cruz Ribeiro

unread,
Apr 13, 2015, 11:02:13 AM4/13/15
to lin...@googlegroups.com, Kay.W...@lsexperts.de, kay.w...@lsexperts.de
HI Kay.

So, you got verify my code ? I´m wait for your reply.

Thanks.

Marcelo.

Kay Winkler

unread,
Apr 14, 2015, 11:34:39 AM4/14/15
to lin...@googlegroups.com
Dear Marcello,

sorry for my late reply but I'm somehow bussy ;-)

So here my 2 Cents wrt. your code:

- you'r currently checking if the cookie: admin_session is set,
- but you need to get the value of the cookie and
- exact this value for usage as a session parameter and
- as well as cookie for your next request


The cookie value for admin_session and session value must be the same!
You can create a cookie value on your own - or use the admin/getsession
to get one from LinOTP


Wrt. the code - you probably only have to add the following line before the curl_exec($ch):

 curl_setopt($c, CURLOPT_COOKIE, 'admin_session=cfe77e971185f42a33e2832dcfd150df23207270c54d4c58b895a281e6f5e20a');

(s. http://docstore.mik.ua/orelly/webprog/pcook/ch11_04.htm)



If you run the admin/getsession call  you can get an initial session value,
which returns the admin_session cookie from which you have to extract
the value for usage in the session.

(s. http://stackoverflow.com/questions/895786/how-to-get-the-cookies-from-a-php-curl-into-a-variable)



Best regards,

    Kay

For more options, visit https://groups.google.com/d/optout.
Kay_Winkler.vcf

Marcelo Cruz Ribeiro

unread,
Apr 16, 2015, 3:18:38 PM4/16/15
to lin...@googlegroups.com, Kay.W...@lsexperts.de, kay.w...@lsexperts.de
Kay.

Thank you so much for your help, I got it enroll Token, your tip about CURLOPT_COOKIE definily was the information that solve the question.

Best Regards.

Marcelo.

Marcelo Cruz Ribeiro

unread,
Apr 16, 2015, 4:39:58 PM4/16/15
to lin...@googlegroups.com
Follow my code, it's function and I hope to help everybody !

Thanks.


<?php
  function geraString(){
    $lut = array(0 => "A",       1 => "B",
                 2 => "C",       3 => "D",
                 4 => "E",       5 => "F",
                 6 => "G",       7 => "H",
                 8 => "I",       9 => "J",
                 10 => "K",      11 => "L",
                 12 => "M",      13 => "N",
                 14 => "O",      15 => "P",
                 16 => "Q",      17 => "R",
                 18 => "S",      19 => "T",
                 20 => "U",      21 => "V",
                 22 => "W",      23 => "X",
                 24 => "Y",      25 => "Z",
                 26 => "2",      27 => "3",
                 28 => "4",      29 => "5",
                 30 => "6",      31 => "7"
    );

    for($x=0;$x<=20;$x++){
      $n = rand(0,31);
      $str_sentence = $str_sentence . $lut[$n];
    }
    return $str_sentence;
  }

  function linotp_init($server){

    $ret = false;
   
    try {
      if (!function_exists("curl_init"))
        die("cURL extension is not installed!");
    
      $session=curl_init('http://'.$server.'/admin/getsession');
      curl_setopt($session,CURLOPT_RETURNTRANSFER, true);
      $s=curl_exec($session);
      curl_close($session);

      $ObjectSession = json_decode($s);
     
      if($ObjectSession->{'result'}->{'status'} == true && $ObjectSession->{'result'}->{'value'} == true){
        $ch=curl_init('http://'.$server.'/admin/init?type=OCRA&genkey=1&sharedsecret=1&otplen=6&description=web ui generated&session='.$_COOKIE["admin_session"]);
        curl_setopt($ch, CURLOPT_COOKIE, 'admin_session='.$_COOKIE["admin_session"]);

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $r=curl_exec($ch);
        curl_close($ch);
        $Object = json_decode($r);

        if (true == $Object->{'result'}->{'status'} && true == $Object->{'result'}->{'value'}){
              $ret=true;
        }else{
              $ret = 'o token n�o foi gerado: '.$Object->{'result'}->{'error'}->{'code'}.'|'.$Object->{'result'}->{'error'}->{'message'};
        }
      }else{
    $ret = 'Sess�o n�o gerada: '.$Object->{'result'}->{'error'}->{'code'}.'|'.$Object->{'result'}->{'error'}->{'message'};

      }
    } catch (Exception $exc) {
      echo $exc->getTraceAsString();
    }
    return $ret;
  }
 

  $str = geraString();
  $tkn_seed = hash_hmac('sha1', $str, '');

  $token = linotp_init('localhost:5001');
  if($token == true){
    echo('token gerado com sucesso');
  }else{
    echo($token);
  }
?>

Moustapha Amadou Diouf

unread,
Jun 25, 2015, 10:37:57 AM6/25/15
to lin...@googlegroups.com
Hello,

This thread is most certainly very interesting.

I would like to ask a question here.
I am developing a Grails application with two factor authentication.

With the past help that I have been getting from the group, I have been able to move very fast.
Right now, I am trying to do admin calls with the API.
With sucess, I was able to use admin/getsession and retrieve the cookie.

I am trying to test the use of that cookie and wrote a simple HTTP request which is :

URLmyUrl2 = new URL("http://localhost:5001/admin/userlist?realm=arya&session="+"${cookieValue}")
URLConnection urlConn2 = myUrl2.openConnection()

urlConn2.setRequestProperty("Cookie", "${cookieName}=${cookieValue}")
urlConn2.connect()

For non-java people, this code allows me to send a cookie with an HTTP request.
However I am still getting the "no valid session" message

I read another interesting post from Kay describing how to do requests correctly and this is what was written:

For the proceeding request you have to put this session as 
+ additional request parameter AND 
+ you have to put this in the admin_session HTTP Cookie. 

I am pretty sure that this is what my code does but I am still getting the no valid session message.
What does : "you have to put this in the admin_session HTTP Cookie" ? mean

Any ideas what I am missing

Have a great day.
Best regards.

Madmous.

Moustapha Amadou Diouf

unread,
Jun 25, 2015, 10:56:18 AM6/25/15
to lin...@googlegroups.com
Hello,

I just wanted to let you know that I finally did it.

All I had to do was create a cookie and set to my admin session like this

Cookie myCookie = new Cookie("${cookieName}", "${cookieValue}")
response.addCookie(myCookie)

I also had to fix my setRequest with 

urlConn2.setRequestProperty("${cookieName}", "${cookieValue}")




Omar Kohl

unread,
Jun 25, 2015, 11:02:43 AM6/25/15
to lin...@googlegroups.com
Hello Madmous,

great to hear that it is working now :-)

On 25/06/15 16:56, Moustapha Amadou Diouf wrote:
> urlConn2.setRequestProperty("${cookieName}", "${cookieValue}")

I think you can simply remove that line. As far as I can see
setRequestProperty sets a HTTP header. There is no need to set a Header
with name 'admin_session'. The reason your previous example didn't work
is that you were probably overwriting the standard Cookie header.

Kind regards,
Omar

--
Omar Kohl, Software Developer
http://www.lsexperts.de
LSE Leading Security Experts GmbH, Postfach 100121, 64201 Darmstadt
Tel.: +49 (0) 6151 86086 -254, Fax: -299, Mobil: +49 (0) 171 2293419
Unternehmenssitz: Weiterstadt, Amtsgericht Darmstadt: HRB8649
Geschäftsführer: Oliver Michel, Sven Walther

Moustapha Amadou Diouf

unread,
Jun 25, 2015, 11:15:18 AM6/25/15
to lin...@googlegroups.com
Hello Omar,

You are right. I was overwriting it.

Thank you.

Best regards.

Moustapha Amadou Diouf

unread,
Jun 25, 2015, 11:35:38 AM6/25/15
to lin...@googlegroups.com
Hello Omar,

Actually could you take a look at my previous post.
I was looking at the wrong JSON. I am still getting the no valid session; sorry for wasting you rime by the way.

Best regards
Madmous

Omar Kohl

unread,
Jun 25, 2015, 12:00:51 PM6/25/15
to lin...@googlegroups.com
Hello Madmous,

I have no experience java.net.* but searching a bit it looks like you
need to set the cookie value with setRequestProperty, like you did in
the beginning.
http://www.hccp.org/java-net-cookie-how-to.html#setting_values

Just make sure the same value is used for the 'session' Parameter and
for the 'admin_session' Cookie. The value can be anything, but it needs
to be equal. Since your URL starts with localhost:5001 I'm assuming you
are running locally with 'paster'. If you run LinOTP with a proper
Webserver (e.g. Apache) with Digest Authentication, then you will also
need to handle this in your script. With paster it should work simply
with the 'session' Parameter and 'admin_session' Cookie.

Kind regards,
Omar
> --
> You received this message because you are subscribed to the Google
> Groups "LinOTP" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to linotp+un...@googlegroups.com
> <mailto:linotp+un...@googlegroups.com>.
> Visit this group at http://groups.google.com/group/linotp.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/linotp/39272b40-1f96-4e30-a3a8-348ea210e93c%40googlegroups.com
> <https://groups.google.com/d/msgid/linotp/39272b40-1f96-4e30-a3a8-348ea210e93c%40googlegroups.com?utm_medium=email&utm_source=footer>.
> For more options, visit https://groups.google.com/d/optout.

Moustapha Amadou Diouf

unread,
Jun 25, 2015, 12:22:26 PM6/25/15
to lin...@googlegroups.com
Hello,

I will take a look at my variables.
I want to take step back for now and make sure I am doing the requests proprely.

Let's take an example.
I get this cookie :
admin_session=2084f6a2079ec99ecbe19f1217990e52d54bb358645b29175bd193f5d1ef1409; Path=/;admin_session=2084f6a2079ec99ecbe19f1217990e52d54bb358645b29175bd193f5d1ef1409; Domain=localhost; Path=/
I extract it and get :
admin_session=2084f6a2079ec99ecbe19f1217990e52d54bb358645b29175bd193f5d1ef1409

Let's take a look at what I should do next (correct me if I am wrong)

All the admin requests should be accompanied with the admin session parameter. I am hesitating a lot on how I should use this parameter

Let's say I want to init a token. I will do this http request :

URL myUrl2 = new URL("http://localhost:5001/admin/" +
"init?" +
"&otpkey=1" +
"&type=HMAC" +
"&otplen=6" +
"&sharedsecret=1" +
/*"userlist?" +
"&realm=arya" +*/
"&${cookie}")

Am I support to add &admin_session=2084f6a2079ec99ecbe19f1217990e52d54bb358645b29175bd193f5d1ef1409
to my url or &session=2084f6a2079ec99ecbe19f1217990e52d54bb358645b29175bd193f5d1ef1409

Best regards.
Madmous

 

Omar Kohl

unread,
Jun 25, 2015, 12:30:44 PM6/25/15
to lin...@googlegroups.com
Hello,

you need to append:
&session=2084f6a2079ec99ecbe19f1217990e52d54bb358645b29175bd193f5d1ef1409
to the URL.

Attached you will find a fully functional Python example. If you are
able to execute it and want to try it with your local 'paster' then you
should remove the 'auth' part because it is not needed. Otherwise you
can just read the code. It should be pretty clear. The example makes a
POST request by the way, but you can still make GET requests like you
are doing, no problem.

Kind regards,
Omar
> --
> You received this message because you are subscribed to the Google
> Groups "LinOTP" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to linotp+un...@googlegroups.com
> <mailto:linotp+un...@googlegroups.com>.
> Visit this group at http://groups.google.com/group/linotp.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/linotp/6c465c36-4123-4b61-87e0-84b95a0db6f4%40googlegroups.com
> <https://groups.google.com/d/msgid/linotp/6c465c36-4123-4b61-87e0-84b95a0db6f4%40googlegroups.com?utm_medium=email&utm_source=footer>.
example.py

Moustapha Amadou Diouf

unread,
Jun 25, 2015, 1:35:35 PM6/25/15
to lin...@googlegroups.com
Hello Omar,

Ok thank you for the example.
Does the admin_session cookie change everytime I make a getsession() request or not ?

Best regards.
Madmous

Omar Kohl

unread,
Jun 25, 2015, 1:49:22 PM6/25/15
to lin...@googlegroups.com
Hello Madmous,

every time you call admin/getsession a new 'admin_session' Cookie with a
new value is set in the response. Therefore yes, it changes in every
request.

But the value itself does not really matter, it is just a random string.
The only requirement is that the 'session' parameter equals the
'admin_session' Cookie. This is to prevent CSRF (Cross Site Request
Forgery) in the Webrowser.

You can use your own value instead of calling admin/getsession, but it
is recommended to use something random, not something that an attacker
could simply guess. But just for arguments sake: you could use '1234' as
session. We recommend: you either call admin/getsession and get a random
value from the server, or use some OS call to generate a random value
(as in the example script I sent you).

Kind regards,
Omar
> --
> You received this message because you are subscribed to the Google
> Groups "LinOTP" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to linotp+un...@googlegroups.com
> <mailto:linotp+un...@googlegroups.com>.
> Visit this group at http://groups.google.com/group/linotp.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/linotp/576cb741-1fe5-482c-81e7-7777eb0d52df%40googlegroups.com
> <https://groups.google.com/d/msgid/linotp/576cb741-1fe5-482c-81e7-7777eb0d52df%40googlegroups.com?utm_medium=email&utm_source=footer>.

Moustapha Amadou Diouf

unread,
Jun 27, 2015, 6:49:55 PM6/27/15
to lin...@googlegroups.com
Hello,

First of all Omar thank you very much.
I took a break after a lot of fail attempts Friday and tonight I decided to look at your Python example.
I realized how easy it was which made me think that I was probably making syntax errors.

All I have to do is add the the cookie value to my url and send in the get request.

Looking back at my code everything was fine so i decided to first make sure I was sending the cookie in the requests proprely.
Then I took a couple of minutes to look at my url which had a mistake.

URL url2 = new URL("http://localhost:5001/admin/show?session="+cookieValue)


Such a silly mistake that I saw after taking a long break.

I have an off topic question

I know sudo paster serve linotp.ini allows to not authenticate the admin by just going to server/manage
If I want to run my LinOTP server like it should be in production, what should I run

I can' thank you enough.
Best regards.
Madmous 

Mirko Ahnert

unread,
Jun 29, 2015, 3:30:18 AM6/29/15
to lin...@googlegroups.com
Dear Madmous,

regarding your question about running LinOTP in production environment: you have to install a web server of your choice and configure it properly. Please have a look at:



If you decide to install LinOTP on Debian or Ubuntu you could use the packages provided of LinOTP which include a working integration in Apache:


Best regards,

Mirko

-- 
Mirko Ahnert 
LSE Leading Security Experts GmbH, http://www.lsexperts.de 
Postfach 100121, 64201 Darmstadt, Germany 
Zentrale: +49 6151 86086-0 , Fax: -299 
Support Hotline: +49 6151 86086-115 
Unternehmenssitz: Weiterstadt Amtsgericht Darmstadt: HRB8649 
Geschäftsführer: Oliver Michel, Sven Walther 

Moustapha Amadou Diouf

unread,
Jun 29, 2015, 8:28:27 AM6/29/15
to lin...@googlegroups.com
Ok,

Thank you Mirko.

Best regards.
Madmous
Reply all
Reply to author
Forward
0 new messages