How to config Redis cache expiration with RedisSessionStateProvider? - asp.net-mvc

I create a MVC sample app uses RedisSessionStateProvider as a custom session state. I set a variable into session state and it works great. But I do not know how to synchronize expiration of items in the session and Redis. Could anyone please help?
This is parameters from web.config
<!--
<add name="MySessionStateStore"
host = "127.0.0.1" [String]
port = "" [number]
accessKey = "" [String]
ssl = "false" [true|false]
throwOnError = "true" [true|false]
retryTimeoutInMilliseconds = "5000" [number]
databaseId = "0" [number]
applicationName = "MvcTestApp" [String]
connectionTimeoutInMilliseconds = "5000" [number]
operationTimeoutInMilliseconds = "1000" [number]
connectionString = "<Valid StackExchange.Redis connection string>" [String]
loggingClassName = "<Assembly qualified class name that contains logging method specified below>" [String]
loggingMethodName = "<Logging method should be defined in loggingClass. It should be public, static, does not take any parameters and should have a return type of System.IO.TextWriter.>" [String]
/>
-->
I am using lateset versions:
RedisSessionStateProvider version 1.6.4
Redis version 2.8.21

The expiration of the session items set in Redis will expire when Session will expire, you don't need to do anything about it. It will be handled by the RedisSessionStateProvider

All session state providers have no attribute about expiration. There is a HttpSessionState.Timeout
Gets and sets the amount of time, in minutes, allowed between requests before the session-state provider terminates the session.
The Timeout property cannot be set to a value greater than 525,600 minutes (1 year). The default value is 20 minutes.
So, asp.net manages for us this logic, we don't need to worry about it.
On redis client, you can use two commands keys * to see all keys, ttl <key> to see when it will be expired.

Related

Websphere 8.5.5.16, OIDC IDToken - user problem

I'm trying to configure Oauth authorization on websphere 8.5.5.16. I added interceptor with issuerIdentifier parameter = https://company.com/abc I next step I added trust external realm: https://company.com/abc And when I try to start service in my app (IBM BPM) I getting an error: NullPointer Exception. Please look at the logs on how the user is created:
Principal: https://company.com/abc/login_user
Public Credential: com.ibm.ws.security.auth.WSCredentialImpl#ebc4e0d2
Private Credential: {setLtpaCookie=false, com.ibm.wsspi.security.cred.securityName=login_user, com.ibm.wsspi.security.cred.uniqueId=user:https://company.com/abc/login_user, token_type=, access_token=xxx, id_token=, com.ibm.wsspi.security.cred.realm=https://company.com/abc, com.ibm.wsspi.security.cred.groups=[], refresh_token=, JsonWebToken=JsonWebToken:{"aud":"0000","iss":"https://company.com/abc","iat":122,"nbf":123,"exp":232,"auth_time":222,"nonce":"aaa","sub":"ddddd/fffff","upn":"login_user","unique_name":"domain\\login_user","pwd_url":"https://company.com/abc/portal/updatepassword/","pwd_exp":"4545","sid":"S-1-5-21-66-117609710","authorities":["Group_1, Group_2"],"given_name":"Name","family_name":"Surname","apptype":"Public","appid":"0000","authmethod":"http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/windows","ver":"1.0","scp":"openid"}}
Private Credential: com.ibm.ws.security.token.SingleSignonTokenImpl#347c9d2b
Private Credential: com.ibm.ws.security.token.AuthenticationTokenImpl#718ea698
Private Credential: com.ibm.ws.security.token.AuthorizationTokenImpl#27e8a5bb
00000187 UserOrgModule 1 com.lombardisoftware.userorg.UserOrgModule getIdFromPrincipalName getIdFromPrincipalName() user=/company.com/abc/login_user, id=null
user = /company.com/abc/login_user not: login_user Why? Please help.
From message "00000187 UserOrgModule", I can tell your BPM application can not help realm name that contains '/' character. You can resolve the problem with following steps:
In your TAI properties, add useRealm property, and give an unique and meaningful value as realm, for example,
provider_.useRealm=abc123
Add "abc123" as trusted realm. This value matches value you define in step 1.
If you assign roles to users unique id, you need reassign roles again with unique id build from this new realm.
Thanks. I did exactly as you wrote.
I added in my interceptor config: provider_1.useRealm=myrealm
I added trusted realm in Global security > Federated repositories > Trusted authentication realms - inbound (Name = myrealm, Trusted).
I restarted server.
Nothing has changed. I still see: user=/company.com/abc/login_user, id=null because in JWT token, in iss field I have value: 'https://company.com/abc' and unfortunately I cannot change this

Where is the port 8080 coming from when spring security redirects to login? How can I change it to use port 443?

In my app, when a URL is listed in a requestMap as 'IS_AUTHENTICATED_FULLY', spring security intercepts and redirects to our login. This is as it should be. However, spring security is adding ':8080' to the login url, which it should not do. I need to figure out how to modify the spring security configuration parameters so that the generated login url does not include the port (or includes the default ports.)
The problem occurs when a non-logged in user enters a url similar to the following:
https://whitelabel.innocentive.com/ar/workspace/index
Spring security intercepts and redirects to login. The url generation looks like this (notice the port 8080):
https://whitelabel.innocentive.com:8080/ar/login/index
I added what I thought were the correct configuration parameters in our config.groovy file (see below). Unfortunately, I still got the :8080 in the generated url
This is happening when the user has not yet logged on. (If there has already been a successful log on, there is no problem.) We use RequestmapConfig.groovy for our requestmaps, which is loaded at the time of booting. Here are pertinent lines:
grails
//Login required
checkCreateRequestmap([configAttribute: 'IS_AUTHENTICATED_FULLY', url: '/board/removesubscription/**'])
checkCreateRequestmap([configAttribute: 'IS_AUTHENTICATED_FULLY', url: '/board/workspace/**'])
checkCreateRequestmap([configAttribute: 'IS_AUTHENTICATED_FULLY', url: '/projectroom/index/**'])
checkCreateRequestmap([configAttribute: 'IS_AUTHENTICATED_FULLY', url: '/workspace/index/**'])
checkCreateRequestmap([configAttribute: 'IS_AUTHENTICATED_FULLY', url: '/federatedLogin/index'])
checkCreateRequestmap([configAttribute: 'IS_AUTHENTICATED_FULLY', url: '/challenge/newChallenge'])
checkCreateRequestmap([configAttribute: 'IS_AUTHENTICATED_FULLY', url: '/solverCenter/**'])
However, I think the real problem is that spring security is not picking up the configuration parameters properly. Here are the spring security parameters taken from config.groovy (httpPort and httpsPort are the last two added:
grails.plugin.springsecurity.userLookup.userDomainClassName = 'Person'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'PersonAuthority'
grails.plugin.springsecurity.authority.className = 'Authority'
grails.plugin.springsecurity.requestMap.className = 'Requestmap'
grails.plugin.springsecurity.securityConfigType = 'Requestmap'
grails.plugin.springsecurity.active = true
grails.plugin.springsecurity.successHandler.defaultTargetUrl = '/login/loginRedirection'
// alwaysUseDefaultTargetUrl=false
grails.plugin.springsecurity.auth.loginFormUrl = "/login/index"
grails.plugin.springsecurity.logout.afterLogoutUrl = '/logout/confirmation'
grails.plugin.springsecurity.adh.errorPage = null
// removing these config as we want the default bcrypt algorithm
//grails.plugin.springsecurity.password.algorithm = 'SHA' // Ex. MD5 SHA
//grails.plugin.springsecurity.password.encodeHashAsBase64 = false
//grails.plugin.springsecurity.password.hash.iterations = 1
grails.plugin.springsecurity.userLookup.passwordPropertyName = 'passwd'
grails.plugin.springsecurity.userLookup.accountExpiredPropertyName = null
grails.plugin.springsecurity.userLookup.accountLockedPropertyName = null
grails.plugin.springsecurity.userLookup.passwordExpiredPropertyName = null
grails.plugin.springsecurity.logout.postOnly = false
//grails.plugin.springsecurity.useSessionFixationPrevention = false
grails.plugin.springsecurity.apf.storeLastUsername = true
grails.plugin.springsecurity.rejectIfNoRule = false
grails.plugin.springsecurity.fii.rejectPublicInvocations = false
// added to cause a new jsessionid to be created after login
grails.plugin.springsecurity.useSessionFixationPrevention=true
grails.plugin.springsecurity.sessionFixationPrevention.migrate=false
grails.plugin.springsecurity.sessionFixationPrevention.alwaysCreateSession=true
grails.plugin.springsecurity.portMapper.httpPort = 80
grails.plugin.springsecurity.portMapper.httpsPort = 443
I would have expected spring security to generate a url with port 443 rather than port 8080:
https://whitelabel.innocentive.com:8080/ar/login/index
Just some background information: Our app used to listen on port 8080, but we have recently moved to the AWS cloud. Our IT has put the application behind a load balancer that listens on 80 and 443. They do not want to add 8080 to the list of listening ports.
Just posting this for those who may have the same issue. Our problem was resolved by adding the following to our tomcat server.xml:
<Valve className="org.apache.catalina.valves.RemoteIpValve" internalProxies="172\.31\.\d{1,3}\.\d{1,3}" remoteIpHeader="x-forwarded-for" proxiesHeader="x-forwarded-by" protocolHeader="x-forwarded-proto" httpsServerPort="x-forwarded-port" />
No configuration changes were needed for our grails application, but our Apache config did get ProxyPreserveHost turned back on.
(One minor note, if we had needed to set server.use-forward-headers, application.properties was the right place to set it, despite my initial reservations.

Clearance Gem | Expire a Session after Closing the Browser in Rails 5?

How do I automatically sign out when the user closes the browser ? Is there any configuration changes in clearance gem that would enable this.
Create A Cookie - Create or set a cookie on user machine having cookie
name, cookie value and the time when cookie should get deleted
automatically (EXPIRES atribute, this is optional). If this is not
specified the cookie is called a session cookie and it expires (gets
deleted) when user's session ends, i.e. when the browser is closed
Source
In other words, if you don't set an expiration date on a cookie, it should "expire" when the browser is closed.
I've never used Clearance, but the ReadMe shows this configuration option in /config/initializers/clearance.rb:
Clearance.configure do |config|
config.allow_sign_up = true
config.cookie_domain = ".example.com"
config.cookie_expiration = lambda { |cookies| 1.year.from_now.utc }
config.cookie_name = "remember_token"
config.cookie_path = "/"
config.routes = true
config.httponly = false
config.mailer_sender = "reply#example.com"
config.password_strategy = Clearance::PasswordStrategies::BCrypt
config.redirect_url = "/"
config.rotate_csrf_on_sign_in = false
config.secure_cookie = false
config.sign_in_guards = []
config.user_model = User
end
If I were you, I'd attempt to set the cookie_expiration to nil. However, if it requires an expiration, you might want to fork the gem and see if the private API here can be altered to your needs.
If you don't want to do that, you can create a guard in Clearance. When a user signs in, set your own cookie with no expiry date. When the user closes the browser, that should delete your custom cookie. Then, in your guard, when the authentication occurs again, you should be able to check for your custom cookie and (upon not finding it) reject the auth and redirect to sign_in.

Is play-mailer an smtp server

I need the functionality to send emails from my Play 2.6.x server. I found that I could use play-mailer (https://github.com/playframework/play-mailer#usage)
Question 1 - Do I need a separate smtp server or is play-mailer an smtp server itself.
Question 2 - At the moment, I am running the application on localhost but I'll eventually deploy it. Would my application work if I just use localhost in the configuration below?
play.mailer {
host = localhost // (mandatory)
port = 25 // (defaults to 25)
ssl = no // (defaults to no)
tls = no // (defaults to no)
tlsRequired = no // (defaults to no)
user = null // (optional)
password = null // (optional)
debug = no // (defaults to no, to take effect you also need to set the log level to "DEBUG" for the application logger)
timeout = null // (defaults to 60s in milliseconds)
connectiontimeout = null // (defaults to 60s in milliseconds)
mock = true// (defaults to no, will only log all the email properties instead of sending an email)
}
Question 3 - Once I deploy the application in the cloud (say AWS), do I just need to change host in the above configuration to make it work?
Question 4 - I am suppose to pass username and password in the play.mailer config. Considering that I version-control my application.conf, is it safe to enter the username and password in the file?
Answer 1:
You will need an smtp server for play.mailer to connect to. This is generally what you'll put in your host in production.
Answer 2:
Yes it should work just like that, I think you'll have to set mock = yes though.
Answer 3:
If you decide to use aws (https://aws.amazon.com/ses/), your conf will look something like this.
play.mailer {
host = "email-smtp.us-east-1.amazonaws.com" // (mandatory) - url from amazon
port = 465 // (defaults to 25)
ssl = yes // (defaults to no)
tls = no // (defaults to no)
tlsRequired = no // (defaults to no)
user = "id_from_amazon"
password = "password_from_amazon"
debug = no // (defaults to no)
timeout = null // (defaults to 60s in milliseconds)
connectiontimeout = null // (defaults to 60s in milliseconds)
mock = no // for actually sending emails. set it to yes if you want to mock.
}
Answer 4:
So the security aspect depends on what environment you're using your play server in. If application.conf is likely to be seen by somebody then you could use environment variables instead of writing it in the application.conf
password = ${APP_MAILER_PASSWORD}
and then set APP_MAILER_PASSWORD as an environment variable. Again, this isn't secure if someone can access the console of your server - but not much is at that point.

Get connection pool status with grails

I have a webservice built with grails that connects to a MySQL database. Since i upgraded to 2.4.3 I've had problems with the connectionpool not releasing the connections, resulting in an exception:
org.apache.tomcat.jdbc.pool.PoolExhaustedException: [http-bio-8080-exec-216] Timeout: Pool empty. Unable to fetch a connection in 30 seconds, none available[size:50; busy:50; idle:0; lastwait:30000]
This is my Datasources.groovy
dataSource {
url = "jdbc:mysql://..."
username = "xxx"
password = "xxx"
pooled = true
properties {
maxActive = 50
maxAge = 10 * 60000
timeBetweenEvictionRunsMillis = 5000
minEvictableIdleTimeMillis = 60000
numTestsPerEvictionRun=3
testOnBorrow=true
testWhileIdle=true
testOnReturn=true
validationQuery="SELECT 1"
}
}
dataSource_survey {
url = "jdbc:mysql://..."
username = "xxx"
password = "xxx"
pooled = true
properties {
maxActive = 50
maxAge = 10 * 60000
timeBetweenEvictionRunsMillis = 5000
minEvictableIdleTimeMillis = 60000
numTestsPerEvictionRun=3
testOnBorrow=true
testWhileIdle=true
testOnReturn=true
validationQuery="SELECT 1"
}
}
I've read grails JIRA and some people seem to have similar problems. But I haven't been able to fix it with the information provided there.
Accessing the status of the connectionpool would help debugging a great deal. How can I check the status of the connectionpool to see how many connections are idle/busy during runtime?
The connection pool is registered as a javax.sql.DataSource but that interface only has methods for getting a Connection (one with username/password and one without), accessing a log writer, and getting/setting the login timeout. Everything else is left to the vendor to decide, and there's very little commonality between vendors in their methods for configuring pools initially, and working with and monitoring them throughout the app run.
So you really need to find out which library is used for the pool and use their API. That would ideally be as simple as accessing the dataSource bean (that's easy, just dependency-inject it into a service/controller/etc. like any bean - as a class-scope field, in this case def dataSource) and printing its class name. But we wrap the datasource in a few proxies to add some important behaviors, so it not easy to access
You're in luck though - for cases like this, we leave the original unproxied instance alone and register it as the dataSourceUnproxied bean which you can also dependency-inject (just don't access any of its connections, only information).
For a long time we used commons-pool to manage datasources, but a while back we switched to the Tomcat JDBC Pool because benchmark tests showed that it's faster than any other they looked at (including C3P0), and its configuration methods are based on commons-pool's, so it was basicallly a drop-in replacement with a significant performance boost and more configurability.

Resources