| Author |  | 
      
        | MrGibbage Super User
 
  
  
 Joined: October 23 2006
 Location: United States
 Online Status: Offline
 Posts: 513
 | 
          My android app that I am developing used commands like
           | Posted: October 25 2011 at 22:35 | IP Logged |   |  
           | 
 |  http://myPhWebServer:8080/ph-cgi/eval?formula=ph_getglobal_s ('ELK_ALARM_STATE_AREA1')
 Using java on android, I would authenticate like this:
 
 String password = db.getWebPassword();
 String username = db.getWebUsername();
 UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password);
 ((AbstractHttpClient) client).getCredentialsProvider().setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), creds);
 HttpGet httpGet = new HttpGet(url);
 HttpResponse execute = client.execute(httpGet);
 
 It worked fine until tonight when I upgraded from 2.1b to 2.14. Previously on 2.1b that code would return just the value of that global
 variable. Now when I run it from my app, something like this is returned:
 powerhome  redirectlocation.replace('/ph-cgi/clogin?nexturl=%2fph-cgi%2 feval%3fformula%3dph_getglobal_s(%27elk_arm_status_area1%27) ')
 
 When I try that url from a web browser, I an authentication rendered within the web page rather than the usual popup that asks for the
 user/pass, which is what used to happen on 2.1b.
 
 Any ideas as to what is going on?
 
 
 __________________
 Skip
 | 
       
        | Back to Top |     | 
       
       
        |  | 
        | dhoward Admin Group
 
  
  
 Joined: June 29 2001
 Location: United States
 Online Status: Offline
 Posts: 4447
 | 
          Skip,
           | Posted: October 25 2011 at 22:39 | IP Logged |   |  
           | 
 |  
 In PowerHome Explorer under PowerHome|Setup|Web, change
 Authentication method from Cookie to Basic.  This will
 revert you back to pre 2.1.4 authentication.
 
 Hope this helps,
 
 Dave.
 
 | 
       
        | Back to Top |       | 
       
       
        |  | 
        | MrGibbage Super User
 
  
  
 Joined: October 23 2006
 Location: United States
 Online Status: Offline
 Posts: 513
 | 
          Whoo hoo, Dave. Thanks!
           | Posted: October 26 2011 at 19:15 | IP Logged |   |  
           | 
 |  
 Do you have any idea how I could configure my app so I can use either method? Is
 there a way for me to tell how a user has their PH webserver configured? Should I
 just try both? Or should I force users to use Basic authentication?
 
 __________________
 Skip
 | 
       
        | Back to Top |     | 
       
       
        |  | 
        | dhoward Admin Group
 
  
  
 Joined: June 29 2001
 Location: United States
 Online Status: Offline
 Posts: 4447
 | 
          Skip,
           | Posted: October 26 2011 at 20:30 | IP Logged |   |  
           | 
 |  
 I would definitely try to support both.  The basic
 authentication is pretty weak.
 
 Not sure if there is a method to determine how the
 webserver is configured (remotely via the app) but I will
 look at the code to make sure.  I'll also try to document
 how the cookie authentication works so that it could be
 supported.  Probably wont get to it until this weekend
 though.  In the meantime, if you're feeling adventurous,
 it should be easy enough to figure out by viewing the
 source of the cookie login page and then the javascript
 file for subsequent page calls.  Its basically just an
 MD5 hash (if memory serves).
 
 Dave.
 
 | 
       
        | Back to Top |       | 
       
       
        |  | 
        | MrGibbage Super User
 
  
  
 Joined: October 23 2006
 Location: United States
 Online Status: Offline
 Posts: 513
 | 
          Well, I am very close. I looked at the source of the login page and watch wireshark as I did some logins and I see how
           | Posted: October 29 2011 at 09:08 | IP Logged |   |  
           | 
 |  it is supposed to work.
 
 I need to POST directly to /ph-cgi/cauth with auth= MD5 hash of token:username:pass
 My code works if I steal an auth from a web browser session. But the token changes each time the login page refreshes.
 Without giving away too much of your backend security, how can I bypass the login page which would be presented to a
 web user? By bypassing that page, I will not have an active token. Or do I just need to hit the login page, grab the
 token, and use it within a certain amount of time? Does ph keep a database of recently presented tokens for future use
 on the login page, and then expire them after a certain amount of time?
 
 Edit:
 I tried saving a token from a web session and then used in in my app about a minute later. It didn't work. I got an error about the
 token being expired.
 
 Edited by MrGibbage - October 29 2011 at 10:05
 
 __________________
 Skip
 | 
       
        | Back to Top |     | 
       
       
        |  | 
        | MrGibbage Super User
 
  
  
 Joined: October 23 2006
 Location: United States
 Online Status: Offline
 Posts: 513
 | 
          Nevermind. I figured it out. I had to first put the token at the front of the auth string and then
           | Posted: October 29 2011 at 12:58 | IP Logged |   |  
           | 
 |  I had to convert it to uppercase. Seems to be working now.
 
 __________________
 Skip
 | 
       
        | Back to Top |     | 
       
       
        |  | 
        | dhoward Admin Group
 
  
  
 Joined: June 29 2001
 Location: United States
 Online Status: Offline
 Posts: 4447
 | 
          Skip,
           | Posted: October 29 2011 at 13:09 | IP Logged |   |  
           | 
 |  
 Still planning to look at the code in depth for you
 (hopefully have something for you tonight) but from
 memory, you'll definitely need to hit the login page and
 scrape the token.  PowerHome has a database table that
 stores the tokens and they do expire.  Once you're
 scraped the token, perform the MD5 hash of the token,
 username, pass and make the call (needs to be done fairly
 quickly because it does expire).  The database will then
 be updated that the token is authenticated and then
 you'll be able to use the cookie for all future calls.
 You can set when tokens expire on the web server
 configuration page.
 
 I'll dig into it and give you further details.
 
 Hope this helps for now.
 
 Dave.
 
 | 
       
        | Back to Top |       | 
       
       
        |  | 
        | MrGibbage Super User
 
  
  
 Joined: October 23 2006
 Location: United States
 Online Status: Offline
 Posts: 513
 | 
          Two quick questions:
           | Posted: October 29 2011 at 13:19 | IP Logged |   |  
           | 
 |  
 1. How can I invalidate a cookie on the server? Or all
 cookies/sessions? I wan tto make sure my app correctly
 handles a situation where I have a cookie but it is
 expired/disabled/whatever on the server and that it tries
 to get a new one.
 2. Is there a function that I can run to change the
 authentication method for the web server between basic and
 cookie?
 
 __________________
 Skip
 | 
       
        | Back to Top |     | 
       
       
        |  | 
        | MrGibbage Super User
 
  
  
 Joined: October 23 2006
 Location: United States
 Online Status: Offline
 Posts: 513
 | 
          Dave,
           | Posted: October 29 2011 at 15:57 | IP Logged |   |  
           | 
 |  Thanks for the help so far. I think I have it all figured out. I do scrape the token from the login
 page and use that to compute the auth key. One thing I have seen though is sometimes when I refresh
 the login page, the token is set to "" (empty string). It doesn't do it every time, but it does
 happen. I haven't decided what I will do when that happens. Maybe retry one or two times before
 giving up.
 
 Anyway, I don't think there is anything else I need you to do right now (except maybe answer my
 question 2 in my post above).
 
 Seriously, thanks for all the help on this. I hope to have a new version of my app out this weekend
 which will add socket server support and basic and cookie authentication for web access.
 
 
 __________________
 Skip
 | 
       
        | Back to Top |     | 
       
       
        |  | 
        | dhoward Admin Group
 
  
  
 Joined: June 29 2001
 Location: United States
 Online Status: Offline
 Posts: 4447
 | 
          Skip,
           | Posted: October 30 2011 at 22:45 | IP Logged |   |  
           | 
 |  
 Dug into the code and pasting my notes below.  Sorry if they're a little jumbled.
 
 A program should make a request as normal (no authentication).  If any request returns a redirect to <html><head><title>PowerHome  Redirect</title><script>location.replace('/ph-cg i/clogin?nexturl=%2f')</script>  then cookie authentication is being used vs basic authentication.  Basic authentication will return a different message (didnt get a chance to look this up but should be easy to see if your server is set basic authentication).  This is the only way to distinguish the authentication the server uses.  Also, anytime the redirect to clogin is returned, a new token should be requested.
 
 If cookie authentication is being used and a new token is needed, a call should be made to
 
 http://phwebserver/ph-cgi/clogin
 
 You now have 5 minutes to create the MD5 hash and make the next call.  If you don't make the call in time, you'll get a token expired message.
 
 Search the HTML returned for:
 
 <input type="hidden" name="token" value="THETOKEN">
 
 The token will always be 8 hex characters.  Make auth string using token:userid:password.  MD5 hash this string.  Now prepend the token to the front of the MD5.  This is the authstring.
 
 Now authenticate the token by calling
 
 http://phwebserver/ph-cgi/cauth?auth=authstring&persist=yes& nexturl=/ph-cgi/main
 
 Verify you get a 200 OK return and a Set-Cookie line.  This ensures that the webtokens table has been properly updated and the token activated.
 For all future requests, just include the cookie: phauth=authstring
 
 The program should store the token once one is received and authenticated.  If any request returns a redirect to <html><head><title>PowerHome  Redirect</title><script>location.replace('/ph-cg i/clogin?nexturl=%2f')</script> </head>
 </html> then the old token should be discarded and a new one received by the method above.
 
 Tokens are stored in the webtokens table.  When a token is first requested via /ph-cgi/clogin, a token is randomly generated and inserted into the table.  The active field will be assigned a value of 0.  If the token isnt authenticated within 5 minutes, it will be deleted from the table.  When /ph-cgi/cauth is called and the token is authenticated, the active field will be changed to either 1 or 2.  If persist is set to no, then the active field will be 1 and then token will expire in 24 hours.  If persist is set to yes and the cookiepersistdays > 0, then the active field will be set to 2 and the token will expire in however many days you've configured for the token to persist in the webserver settings.
 
 The only way to view the existing webtokens is via SQL in the PowerHome Multi-editor in SQL mode (shift-F5).  You can see everything by typing
 
 select * from webtokens
 
 In the to do list is a new screen to manage the web tokens table.
 
 Hope this helps and if you have any questions, I should be prepared to answer them now.
 
 Dave.
 
 | 
       
        | Back to Top |       | 
       
       
        |  | 
        | MrGibbage Super User
 
  
  
 Joined: October 23 2006
 Location: United States
 Online Status: Offline
 Posts: 513
 | 
          This is awesome, Dave, and incredibly helpful. I have just about finished up the work I wanted to do over
           | Posted: October 31 2011 at 06:14 | IP Logged |   |  
           | 
 |  the weekend on the app and I will be test driving it for a day or two before uploading it. This has enabled
 me to add a lot of functionality to the app and I think I will be able to release it to the market Real
 Soon.
 
 __________________
 Skip
 | 
       
        | Back to Top |     | 
       
       
        |  |