Unable to login to Application using CAS and Spring security - grails

1.
I have setup a CAS server up and running at port: 8443 url -> https://ekansh/cas.
I can see the login page and i am successfully able to login using mysql database user table credentials. and even logout and see status.
I created a demo grails app, installed spring security plugin and created user role mappings by s2-quickstart. and scaffolding domains.
I added the
compile ":spring-security-core:2.0-RC4"
compile ":spring-security-cas:2.0-RC1"
dependencies.
Added configurations in Config.grovy
grails.plugin.springsecurity.cas.active = true
grails.plugin.springsecurity.cas.loginUri = '/login'
grails.plugin.springsecurity.cas.sendRenew = false
grails.plugin.springsecurity.cas.serviceUrl = 'http://ekansh:8095/app1/j_spring_cas_security_check'
grails.plugin.springsecurity.cas.serverUrlEncoding = 'UTF-8'
grails.plugin.springsecurity.cas.key = 'grails-spring-security-cas'
grails.plugin.springsecurity.cas.artifactParameter = 'ticket'
grails.plugin.springsecurity.cas.serviceParameter = 'service'
grails.plugin.springsecurity.cas.filterProcessesUrl = '/j_spring_cas_security_check'
grails.plugin.springsecurity.cas.proxyCallbackUrl = 'http://ekansh:8095/app1/secure/receptor'
grails.plugin.springsecurity.cas.useSingleSignout = true
grails.plugin.springsecurity.cas.serverUrlPrefix = 'https://ekansh:8443/cas'
grails.plugin.springsecurity.cas.proxyCallbackUrl = 'http://ekansh:8095/app1/secure/receptor'
grails.plugin.springsecurity.cas.proxyReceptorUrl = '/secure/receptor'
grails.plugin.springsecurity.logout.afterLogoutUrl ='https://ekansh:8443/cas/logout?url=http://ekansh:8095/app1/'
grails.plugin.springsecurity.providerNames = ['casAuthenticationProvider']
Nw when i run this app, i get redirected to cas server page, i enter the credentials, it logs me into cas server, but it sends me to the spring security login page with message that
Sorry, we were not able to find a user with that username and password. And i am not even able to sign in to the application from this point.
What am i missing ? Why am i getting spring security login page.
I also found that when i comment line grails.plugin.springsecurity.providerNames = ['casAuthenticationProvider'], i am able to login to the system. I have not altered the casAuthenticationProvider.
Any help would be appriciated.

I found the answer to my question after a lot of research. Basically i did mess up with the configurations of the cas server.
The user was getting logged into the cas server but a ticket was not being generated for the same user, thus it was still sending a user not authenticated response back to the application and spring security, was redirecting to the login page.

Related

Share session data between Flask apps in separate Docker containers that are served using a reverse proxy

I have a Docker app running on localhost. There are multiple flask apps each in its own container. One is on the root (localhost) and the others are on subdomains (app.localhost). I use a traefik reverse proxy to serve the containers.
Without any authentication, the whole Docker app works great.
Then I try to authenticate the users. I am using Microsoft Authentication Library(Azure AD) for this. On the root app (localhost) this works great. If I am not logged in, it redirects me to a login page with a link. I click the link and now I am authorized. I am also able to pull the username from the http header.
However, when I go to a subdomain (app.localhost), it forgets I am logged in and then crashes because I try to run the same code of pulling the username from the http header, but it is missing.
Code for root app:
app = Flask(__name__)
app.config.from_object(app_config)
Session(app)
# login functions ######################################################################################
def _load_cache():
cache = msal.SerializableTokenCache()
if session.get("token_cache"):
cache.deserialize(session["token_cache"])
return cache
def _save_cache(cache):
if cache.has_state_changed:
session["token_cache"] = cache.serialize()
def _build_msal_app(cache=None, authority=None):
return msal.ConfidentialClientApplication(
app_config.CLIENT_ID, authority=authority or app_config.AUTHORITY,
client_credential=app_config.CLIENT_SECRET, token_cache=cache)
def _get_token_from_cache(scope=None):
cache = _load_cache() # This web app maintains one cache per session
cca = _build_msal_app(cache)
accounts = cca.get_accounts()
if accounts: # So all accounts belong to the current signed-in user
result = cca.acquire_token_silent(scope, account=accounts[0])
_save_cache(cache)
return result
#app.route('/login/')
def login():
session["state"] = str(uuid.uuid4())
auth_url = _build_msal_app().get_authorization_request_url(
app_config.SCOPE,
state=session["state"],
redirect_uri=url_for("authorized", _external=True))
return render_template('login.html', auth_url=auth_url)
#app.route("/auth") # This absolute URL must match your app's redirect_uri set in AAD
def authorized():
if request.args['state'] != session.get("state"):
return redirect(url_for("login"))
cache = _load_cache()
result = _build_msal_app(cache).acquire_token_by_authorization_code(
request.args['code'],
scopes=app_config.SCOPE,
redirect_uri=url_for("authorized", _external=True))
if "error" in result:
return "Login failure: %s, %s" % (
result["error"], result.get("error_description"))
session["user"] = result.get("id_token_claims")
_save_cache(cache)
return redirect(url_for("index"))
def get_token(scope):
token = _get_token_from_cache(scope)
if not token:
return redirect(url_for("login"))
return token
#app.route("/logout")
def logout():
session.clear() # Wipe out the user and the token cache from the session
return redirect( # Also need to log out from the Microsoft Identity platform
"https://login.microsoftonline.com/common/oauth2/v2.0/logout"
"?post_logout_redirect_uri=" + url_for("index", _external=True))
# actual app ##########################################################################################
#app.route('/')
def index():
# send to login page if user is not logged in
if not session.get('user'):
return redirect(url_for('login'))
else:
return render_template('index.html')
app_config.py
from os import environ
CLIENT_SECRET = environ["CLIENT_SECRET"]
AUTHORITY = environ["AUTHORITY"]
CLIENT_ID = environ["CLIENT_ID"]
SCOPE = ["User.ReadBasic.All"]
SESSION_TYPE = "filesystem"
A copy of this app_config file is in the directories for each flask app.
I tried adding this to the app_config files, but apparently localhost doesn't work as the cookie domain.
SESSION_COOKIE_NAME='localhost'
SESSION_COOKIE_DOMAIN='localhost'
REMEMBER_COOKIE_DOMAIN='localhost'
Then I read somewhere that dev.localhost could work. So I changed the Docker app to run on dev.localhost instead of localhost and added this to the app_config.
SESSION_COOKIE_NAME='dev.localhost'
SESSION_COOKIE_DOMAIN='dev.localhost'
REMEMBER_COOKIE_DOMAIN='dev.localhost'
This seemed liked it may work, but Microsoft doesn't allow dev.localhost/auth to be a redirect uri.
What do I need to do for the session to carry between subdomains/other flask apps?
Unfortunately I have to use Windows containers on a Windows Server 2019. I know they are not the best, but it is what I have to work with.

OntoText GraphDb OAuth2 login in using Azure

I am trying to integrate AzuerAD OAuth authentication with graph-db following the instructions https://graphdb.ontotext.com/documentation/free/access-control.html and can't understand the reason it is failing.
My graphdb.properties config is as follows:
graphdb.auth.methods = basic, gdb, openid
graphdb.auth.openid.issuer = https://login.microsoftonline.com
graphdb.auth.openid.client_id = 596251be-....from AD
graphdb.auth.openid.username_claim = email
graphdb.auth.openid.auth_flow = code
graphdb.auth.openid.token_type = access
Also had failed attempted with:
graphdb.auth.openid.issuer = https://login.microsoftonline.com/da0adc10-UUID/oauth2/v2.0/token
I can successfully login to:
https://login.microsoftonline.com/da0adc10-UUID/oauth2/v2.0/authorize?client_id=596251be-from-AD&scope=openid&response_type=code. It's a success because after signing it prompts me with a reminder for a setting.
However, when the redirection happens to http://localhost:7200/login, it fails. (Also tried setting redirect uri to http://localhost:7200/login which was also a failure).
Failure (seen on Network tab of browser):
http://localhost:7200/login?code=0.AUIAENwK2txuskGrQ9UmuxHFYL5RYlkgP---lenghty-stuff---&session_state=dd3f6443-some-string
...eventually...
Request URL: http://localhost:7200/rest/security/authenticatedUser
Request Method: GET
Status Code: 401
Can you provide any guidance?
The redirect URL should be the basic URL of the GraphDB server, which in your case seems to be http://localhost:7200/. It won't work with http://localhost:7200/login.

Login to external site from Rails

I would like to login to an external https site, through rails based on user/password credentials saved into a rails database. Something like a single sign on. The external site does not provide an API to login; only a login form. Their docs say you can post the credentials to their login form by loading the email and password to the form and then pressing ok.
But if I do that, then by viewing the source code of the login form, someone may find out the login credentials. I have looked into Mechanize and loading cookies like here Submitting POST data from the controller in rails to another website and Rails 3 - Log into another site and keep cookie in session but it does not seem right.
Is there a way to automatically load the credentials from the controller and post to the external site immediately in order to login to that site?
Thank you in advance
I would use Oauth2. Here is a good wrapper: https://github.com/intridea/oauth2
I was able to do this via mechanize. For facebook for example, which uses https, the code is shown below
In my user_controller.rb:
def face_book
#website = 'https://www.facebook.com/login.php?login_attempt=1&lwv=110'
agent = Mechanize.new
agent.log = Logger.new "mechanize.log"
agent.user_agent_alias = 'Mac Safari'
agent.follow_meta_refresh = true
agent.redirect_ok = true
login_page = agent.get (#website)
login_form = login_page.forms.first
email_field = login_form.field_with(name: "email")
password_field = login_form.field_with(name: "pass")
email_field.value = 'PUT_YOUR_EMAIL_HERE'
password_field.value = 'PUT_YOUR_PASSWORD_HERE'
home_page = login_form.click_button
#blah = agent.get("https://m.facebook.com/")
end

Grails 2 with spring security: defaultFailureUrl not working

I'm playing around with the grails 2 framework in addition with the spring-security-plugin.
I built a custom login form, which should be always visible on the main page.
Thus, the user should always be redirected to the main page. Regardless of whether an error occurs or not.
In the case of a successful login everything works very well, but in the case of an error the flash scope is lost during the redirect. So I can't display the reason for the failed authentication.
According to the documentation, only the parameter 'defaultFailureUrl' should be adjusted.
But this doesn't work as expected.
Are there any other parameters necessary to achieve this functionality?
My Config.groovy
// Added by the Spring Security Core plugin:
grails.plugin.springsecurity.successHandler.defaultTargetUrl="/"
grails.plugin.springsecurity.successHandler.alwaysUseDefault=true
grails.plugin.springsecurity.failureHandler.defaultFailureUrl = '/'
grails.plugin.springsecurity.auth.loginFormUrl = '/'
grails.plugin.springsecurity.logout.postOnly = false // Logout through direct link
grails.plugin.springsecurity.userLookup.userDomainClassName = 'de.msg.login.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'de.msg.login.UserRole'
grails.plugin.springsecurity.authority.className = 'de.msg.login.Role'
I hope someone can figure out a solution ;)
As I understood you want to show the message on same login page after submit the login page.
Use this property probably it will work :
set this in config.groovy
failureHandler.useForward=false
See this link

Grails 2.1.0 app tomcat 7.0.22 Session empty after redirect

I am just learning grails and have a problem with an app that works fine when I run it in Netbeans but shows strange behavior when deployed to Tomcat 7.0.22 on a Centos 5.4 server. I am using the proxy_ajp to make the app available with apache.
The problem seems to be with the session not being maintained after a redirect so that I lose the login information causing the app to try to login again.
My proxy_ajp settings are
<Location /PreyerBooks >
ProxyPass ajp://localhost:8011/PreyerBooks
ProxyPassReverse ajp://localhost:8011/PreyerBooks
</Location>
the app is deploying without errors and the connectivity to the database and LDAP is working. I tested this by logging in the authenticate method as follows
UserController - authentication function
def authenticate = {
def password=passhash(params.password)
log.info " login attempt ${params.login} - ${params.password} - ${password}"
def match = User.findAll(
directory: "user",
filter: "(&(uid=${params.login})(userpassword=${password}))"
)
log.info " match ${match}"
if (match) {
def user = Employee.findByLogin(params.login)
log.info " user ${user} - ${user?.role}"
if(user){
session.user = user
log.info "success"
flash.message = "Hello ${user.firstname}!"
redirect(controller:"Book", action:"index")
}else{
log.error "failed login attempt mismatch to ldap ${params.login}"
flash.message = "Sorry, ${params.login}. Please try again."
redirect(action:"login")
}
}else{
log.error "failed login attempt ${params.login} - ${params.password}"
flash.message = "Sorry, ${params.login}. Please try again."
redirect(action:"login")
}
}
BookController - auth function (checks if logged in)
def beforeInterceptor = [action:this.&auth, except:[]]
def auth() {
log.info "BookController:auth() ${session}"
if(!session.user) {
redirect(controller:"User", action:"login")
return false
}
log.info "BookController:auth() working"
return true
}
The log shows
INFO books.UserController - login attempt username - password - passwordhash
INFO books.UserController - match [de.preyer.books.User#d4a1cc]
INFO books.UserController - user username - admin
INFO books.UserController - success
INFO books.BookController - BookController:auth() Session Content:
The session.user variable has vanished. I checked the passwordhash and it correctly matches against the LDAP server (hence the object reference in match). This user is correctly found in the database where it gains its role.
I cannot access the app directly avoiding the apache ajp as the port is blocked in the firewall and I cannot open it. Thus I cannot test if the problem is in the ajp or tomcat in general
I have tried searching for the criteria specified as the title but find nothing relevant.
a) browser cookies are enabled and working, I tried Safari, Firefox and Chrome without success. I do not think this is a browser issue as the same browsers work with the app in NetBeans (using jetty I think)
b) I have set grails.serverURL = "http://servername/PreyerBooks" to the fully qualified domain
If I turn of the auth the app works.
I must be doing something wrong or have missed a step in the deployment.
Now I know I can include a plugin using Spring Core but this is overkill for my application and adds a further level of complexity to the debugging. I wish to get the current implementation working before moving on. The logic is copied from the Grails 2.1.0 documentation so it should work.
I read in httpSession that things must be serializable but if the example in the documentation does not work why does the app work when I run it in NetBeans?
I am at a loss. Any help would be much appreciated.
Use the spring-security-core plugin (or Shiro, or any established, proven security implementation). It's not complex, and rolling your own security is a quick path to getting hacked.

Resources