why /cas/login?username=xxx&password=yyyy does not work?

112 views
Skip to first unread message

Richard Yang

unread,
Feb 2, 2017, 3:47:23 PM2/2/17
to CAS Community
I am using cas 4.2.7
http://localhost/cas/login?username=xxx&password=yyyy just gives me the default cas login page.
I understand I may need to attache a "login ticket" if not submitting a login form, but how to get a login ticket?

The reason I want to use the cas login api in http request is to integrate cas sso with our existing login page.
Please do not tell me I can custom my current login page with cas's jsp form based login. It is just too much work and jsp to us is a very old technology and not to be considered for new development.

Thanks.

Richard

Carlos Fernandez

unread,
Feb 2, 2017, 4:41:10 PM2/2/17
to cas-...@apereo.org
There's an old thread in which Scott Battaglia explained why that's not supported, but mainly it's because the application should not be aware of the user's password.

http://jasig.275507.n4.nabble.com/authenticating-a-user-via-URL-parameters-td2067870.html

His suggestion of interacting with CAS programmatically is actually quite simple.


--
- CAS gitter chatroom: https://gitter.im/apereo/cas
- CAS mailing list guidelines: https://apereo.github.io/cas/Mailing-Lists.html
- CAS documentation website: https://apereo.github.io/cas
- CAS project website: https://github.com/apereo/cas
---
You received this message because you are subscribed to the Google Groups "CAS Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cas-user+unsubscribe@apereo.org.
To view this discussion on the web visit https://groups.google.com/a/apereo.org/d/msgid/cas-user/3a86ad29-c804-4c44-bc57-6389fdf2bd67%40apereo.org.



--

Best regards,
--
Carlos M. Fernández
Enterprise Systems Manager

Saint Joseph’s University
Philadelphia PA 19131
T: +1 610 660 1501

Christopher Myers

unread,
Feb 3, 2017, 8:59:09 AM2/3/17
to cas-...@apereo.org
If you put parameters like that in the URL, it'd be a HUGE security risk...username and password would be stored in cleartext in browser history, server logs, possibly firewall/load balancer logs, etc.

There is this workaround that you can do though; this hasn't been tested with CAS 5, but does work with 3.x and 4.x; code has been anonymized a bit and some pieces chopped out, but this should give you a good starting point. It also comes with the usual "no warranties, make sure you know what this is doing, use at your own risk" disclaimer. And, make sure you secure this somehow so that only a very select, heavily audited group of folks can use it...!! (There are extra steps with this stuff posted below that can potentially be eliminated, but they offer the ability to add extra layers of protection.)





Post username to this URL:





/path/to/emulate.jsp







Which contains stuff like this:





<%@page contentType="text/html; charset=windows-1252" isELIgnored="false"
%>

<%

  try {

    String userName = request.getParameter("username");
    String userPassword = "";

    try {

      if (request.getParameter("username") != "") {
         userPassword = howeverYouGetThePasswordForTheUser(userName);
      }


%>
<html>
  <body onload='setTimeout("document.forms.logon.submit()",1000)'>
    <iframe src='https://servername.domain.com/public/logout.jsp' width='0' height='0'></iframe>
    Loading...
    <form name="logon" method="post" action="https://<%=config.getServletContext().getInitParameter("casServer").toLowerCase()%>/casLogin.jsp">
      <input type="hidden" name="username" value="<%=userName%>">
      <input type="hidden" name="password" value="<%=userPassword%>">
    </form>
  </body>
</html>
<%

    } catch (Exception e) {
      e.printStackTrace(new java.io.PrintWriter(out));
      String myException = String.valueOf(e);
    }
  } catch (Exception e) {
    e.printStackTrace(new java.io.PrintWriter(out));
    String myException = String.valueOf(e);
  }
%>








Which posts to this file that you put in your CAS server's Tomcat ROOT folder (so that it will look something like https://cas.something.com/casLogin.jsp) ::







<%@page contentType="text/html; charset=windows-1252" isELIgnored="false"
        import="java.net.URL"
        import="java.net.HttpURLConnection"
        import="java.io.InputStream"
        import="java.io.BufferedReader"
        import="java.io.InputStreamReader"
%>

<%
  response.setHeader("Cache-Control","no-cache"); //HTTP 1.1
  response.setHeader("Pragma","no-cache"); //HTTP 1.0
  response.setDateHeader ("Expires", -1); //prevents caching at the proxy server

  String testURL = "https://" + String.valueOf(request.getServerName()) + "/cas/login";
  String myService = request.getParameter("service");
  String myReferer = request.getHeader("referer");
  String username = request.getParameter("username");
  String password = request.getParameter("password");

  if (myReferer == null) { myReferer = ""; }
  if ((myService != null) && (myService != "")) {
    testURL = testURL + "?service=" + myService;
  } else if (myReferer.indexOf("emulate") > -1) { //If called from the "emulate.jsp" page, redirect to the root of the secured path
    testURL = testURL + "?service=" + "https%3A%2F%2F" + "servername.domain.com" + "%2Fservlet%2FsecuredPath%2F";
  }

  String myLT = "";
  String myExecution = "";
  URL myUrl = new URL(testURL);
  HttpURLConnection myUrlConnection = (HttpURLConnection)myUrl.openConnection();

  myUrlConnection.setDoInput(true);
  myUrlConnection.setDoOutput(false);

  String myCookie = myUrlConnection.getHeaderField("Set-Cookie");
  myUrlConnection = (HttpURLConnection)myUrl.openConnection();

  if (myCookie != null) {
    myUrlConnection.setRequestProperty("Cookie", myCookie);
  }

  myUrlConnection.setDoInput(true);
  myUrlConnection.setDoOutput(false);

  response.addHeader("Set-Cookie", myCookie);
  response.setContentType("text/html");

  if (null != (myCookie = myUrlConnection.getHeaderField("Set-Cookie"))) {
    response.addHeader("Set-Cookie", myCookie);
  }

  InputStream webContent = (InputStream)myUrlConnection.getInputStream();
  BufferedReader pageStream = new BufferedReader (new InputStreamReader (webContent));
  String currentLine = "";
  String debugOutput = "";

  if (myUrlConnection.getResponseCode() == 200){ //Makes sure that the page pulled correctly and didn't give an error
    while ((currentLine = pageStream.readLine()) != null) {
      if (currentLine.toLowerCase().indexOf("name=\"lt\"") > -1) {
        myLT = currentLine.substring(currentLine.indexOf("value=") + 7,currentLine.length() - 4);
      } else if (currentLine.toLowerCase().indexOf("name=\"execution\"") > -1) {
        myExecution = currentLine.substring(currentLine.indexOf("value=") + 7,currentLine.length() - 4);
      }
    }
  }
  pageStream.close();

%>

<html>
<head>
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Expires" CONTENT="-1">

</head>
<body onload="document.forms.loginForm.submit()">
Loading...
  <form name="loginForm" action="<%=testURL%>" method="POST">
    <input type="hidden" name="username" value="<%=username%>">
    <input type="hidden" name="password" value="<%=password%>">
    <input type="hidden" name="lt" value="<%=myLT%>" />
    <input type="hidden" name="execution" value="<%=myExecution%>">
    <input type="hidden" name="_eventId" value="submit" />
  </form>
</body>
</html>






















>>> Richard Yang <richar...@pearson.com> 02/02/17 2:47 PM >>>
--
- CAS gitter chatroom: https://gitter.im/apereo/cas
- CAS mailing list guidelines: https://apereo.github.io/cas/Mailing-Lists.html
- CAS documentation website: https://apereo.github.io/cas
- CAS project website: https://github.com/apereo/cas
---
You received this message because you are subscribed to the Google Groups "CAS Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cas-user+u...@apereo.org.

Gilbert, Howard

unread,
Feb 3, 2017, 9:35:21 AM2/3/17
to cas-...@apereo.org

Setting aside the question of whether this is a good idea and answering the literal question of why it doesn’t work, the CAS login is coded in Spring Webflow. There is an initialization step and then a sequence of test (like is the user already logged in with a CASTGC cookie, and only after that is the form displayed and then the response is processed. The flow maintains state for a “conversation” that begins at initialization, and you cannot jump into the middle of the flow and respond to a form that was never sent to you because, among other things, the service=xxxx value is stored in the conversation state and cannot be submitted with the form. When the Flow discovers there is no saved state, it starts over again at the beginning.

 

You would have to recode the entire WebFlow to allow a “naked” POST (or in this case a naked GET). We did this, but not for the reason you give. For some undisclosed reason that we were never able to debug, a few times a day a random person would lose his or her conversation state (not for the obvious reason that it timed out) and would complain that they had to submit their userid/password twice to login to CAS. Since we could not get whatever network or HTTPS problem to go away, we recoded the Flow so if you came to the start of the flow with a POST instead of a GET it would fix everything up and then jump to the middle state in the flow that handles form submission. To do this, you have to add a hidden input field with the service= value. I do not recommend doing all this work, but as a result I can explain what is the cause of the restriction you encounter.

Menno en Erla Avegaart

unread,
Feb 6, 2017, 5:56:50 AM2/6/17
to CAS Community
As mentioned in all the other responses, security wise this is NOT a good idea.

But sometimes your boss just wants this and you can't refuse. So I added a little javascript to the login page:

$(document).ready(function(){
    var params = {},
        search = window.location.search.substr(1);
    search.replace(/([^?=&]+)(=([^&]*))?/g, function(p0, name, p2, value) {
        params[name] = decodeURIComponent(value);
    });
    if (params.usr && params.pwd && $('#fm1').length && !$('#msg').length) {
        $('#username').val(params.usr);
        $('#password').val(params.pwd);
        $('#fm1 [type=submit]').click();
    }
});

Note: I used 'usr' and 'pwd' parameters so CAS doesn't confuse them with the inputs named 'username' and 'password'.


Op donderdag 2 februari 2017 21:47:23 UTC+1 schreef Richard Yang:

Vincent N.

unread,
Feb 15, 2017, 6:09:55 AM2/15/17
to CAS Community
We had the same issue, but we fixed it using the REST API (using some javascript), and will migrate soon using the JWT (more secure). These are valuable alternatives, all implemented in the CAS v4.2.x server ...

Vincent
Reply all
Reply to author
Forward
0 new messages