FOSUserBundle Can only login one time - session

I'am trying to using the FOSUserBundle with Symfony 3.0.9.
After doing the tutorial here I was able to register a user and login with it, yesterday. The problem was that I couldn't login this morning with the same credentials. After a some tests I noticed that it's not possible to login with the user, when I closed the window.
So i have to delete the user from database and create a new one.
Can anybody help me out to fix this problem?
Surely a user should be able to login, logout and close the brwoser without a logout.
My SecurityController.php:
class SecurityController extends Controller
{
/**
* #Route("/login", name="login")
*/
public function loginAction(Request $request)
{
$authenticationUtils = $this->get('security.authentication_utils');
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render(
'security/login.html.twig',
array(
// last username entered by the user
'last_username' => $lastUsername,
'error' => $error,
)
);
}
}
security.yml:
# To get started with security, check out the documentation:
# http://symfony.com/doc/current/book/security.html
security:
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
fos_userbundle:
id: fos_user.user_provider.username
firewalls:
# disables authentication for assets and the profiler, adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_token_generator: security.csrf.token_manager
logout: true
anonymous: true
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
At least my user entity in database:

The problem was that the session was set by /register and my /login never worked.
With the standard FOSUser Login it worked without problems.

Related

Cypress and auth app with sections. Can you call a shared test, ie login?

I'm new to cypress. Lets say I have the following structure. Each should be run in a vacuum, BUT they all require a login. I understad I could create a "command" that for login. but lets say I have a test, ala login.spec.js
And all it does is log in a user and redirects. Great.
BUT, after that, various devs will want to run their own tests given their particular domains. But they will all need to login, so rather than always creating the same test.. is there a way to "share" a test, then continue on with the tests that they are interested in?
For example: ** FOLDER NAME **
**Integration**
login.spec.js
**CreateProduct**
index.spec.js
**PurchaseProduct** // <-- I want to run this, BUT with login.spec.js too as a before hook.
index.spec.js
etc...
Now, I want to just run the tests in the PurchaseProduct folder, BUT they need to first be "logged in"... so, I want to call login.spec.js... HOW can that be used across all usages of those who want to borrow it?
Yes, Cypress supports the ability to create and reuse actions and state in your UI, such as registering and logging in before a test.
However, Cypress, through cy.request() allows you to control the state of the browser more powerfully than a user would, making your tests simpler, faster, more reliable
Check out this example below where cy.request is used to create/read state on your server.
In commands/index.js:
Cypress.Commands.add('login', (user) => {
cy.request('POST', `${apiUrl}/users/login`, user)
})
Cypress.Commands.add("register", (user) => {
cy.request('POST', `${apiUrl}/users/register`, user)
})
Cypress.Commands.add('getUser', (username) => {
return cy.request('GET', `${apiUrl}/users/${username}`)
})
in register.spec.js:
it ('can register', () => {
const user = {
name: 'jake',
email: 'jake#jake.com',
password: '12345'
}
cy.visit('/register')
cy.get('input[name="name"]').type(user.name)
cy.get('input[name="email"]').type(user.email)
cy.get('input[name="password"]').type(user.password)
cy.get('input[name="password-confirm"]').type(user.password)
cy.get('input[type="submit"]').click()
// ensure register page sends you /home after register
cy.url().should('contain', '/home')
// expect user from server to match user from test
cy.getUser(user.name)
.then((dbUser) => expect(dbUser).to.deep.eql(user))
})
in login.spec.js:
it('can log in', () => {
const user = {
name: 'jane',
email: 'jane#jane.com',
password: '12345'
}
// register w/out UI
cy.register(user)
cy.visit('/login')
cy.get('input[name="name"]').type(user.name)
cy.get('input[name="password"]').type(user.password)
cy.get('input[type="submit"]').click()
// ensure the login page sends you home after login
cy.url().should('contain', '/home')
})
in userSettings.spec.js:
it('can change email', () => {
const user = {
name: 'jane',
email: 'jane#jane.com',
password: '12345'
}
// register and login w/o UI
cy.register(user)
cy.login(user)
cy.visit('/settings')
cy.get('input[name="email"]').type('UpdatedEmail#jane.com')
cy.get('input[type="submit"]').click()
cy.getUser(user.name)
.then((dbUser) => expect(dbUser.email).to.eql('UpdatedEmail#jane.com'))
})
You understand you could create a command for login. Any reason for not doing so then ?
If you haven't already, I recommend watching this presentation from Cypress's founder Brian Mann, referenced on one of the official doc pages. Please find below two sections that seem to relate to your question.
3 strategies to test the login page (8:40)
stub requests, don't actually authenticate
OR static user in the DB
OR dynamic user created by tests
Centralize login (15:35)
(9 minutes later) We don't have to, nor should you ever, use the UI to
build up state

Cognito admin_initiate_auth responds with exception User does not exist when creating a new user

I'm trying to create a new user in a Cognito user pool from my ruby backend server. Using this code:
client = Aws::CognitoIdentityProvider::Client.new
response = client.admin_initiate_auth({
auth_flow: 'ADMIN_NO_SRP_AUTH',
auth_parameters: {
'USERNAME': #user.email,
'PASSWORD': '123456789'
},
client_id: ENV['AWS_COGNITO_CLIENT_ID'],
user_pool_id: ENV['AWS_COGNITO_POOL_ID']
})
The response I get is Aws::CognitoIdentityProvider::Errors::UserNotFoundException: User does not exist.
I'm trying to follow the Server Authentication Flow (https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow.html), and from that I understood that I could create a new user using admin_initiate_auth.
Am I doing something wrong here?
Thanks
You're using the wrong method. admin_initiate_auth is for logging in/authenticating a user with the ADMIN_NO_SRP_AUTH turned on.
You need to use the sign_up method:
resp = client.sign_up({
client_id: "ClientIdType", # required
secret_hash: "SecretHashType",
username: "UsernameType", # required
password: "PasswordType", # required
user_attributes: [
{
name: "AttributeNameType", # required
value: "AttributeValueType",
},
],
validation_data: [
{
name: "AttributeNameType", # required
value: "AttributeValueType",
},
],
analytics_metadata: {
analytics_endpoint_id: "StringType",
},
user_context_data: {
encoded_data: "StringType",
},
})
You can find it in the AWS Cognito IDP docs here.

MongoDB GridFS authentication not working

I am trying to insert data to a MongoDB 3.4 GridFS storage with enabled authentication via a Spring Boot app, but I keep getting this error:
Query failed with error code 13 and error message 'not authorized on user to execute command { find: \"fs.files\", filter: { metadata.fieldname: \"someContent\" } }' on server ip:27017"
I created a user with "superuser" rights for this:
use admin
db.createUser(
{
user: "admin",
pwd: "password",
roles:["root"]
})
My spring boot application.properties are:
spring.data.mongodb.host=ip
spring.data.mongodb.port=27017
spring.data.mongodb.username=admin
spring.data.mongodb.password=password
spring.data.mongodb.database=user
spring.data.mongodb.authentication-database=admin
I already tried the "old" MongoDB roles with no luck:
db.createUser(
{
user: "admin",
pwd: "password",
roles: [
{ role: "userAdminAnyDatabase", db: "admin" },
{ role: "readWriteAnyDatabase", db: "admin" },
{ role: "dbAdminAnyDatabase", db: "admin" },
{ role: "clusterAdmin", db: "admin" }
]
})
Reading and writing to other (non-gridFS) databases works perfectly.
Any ideas on how to solve this?
Solution:
I still had an AbstractMongoConfiguration class lying around.
#Configuration
public class SpringMongoConfig extends AbstractMongoConfiguration {
//some code...
}
Deleting it solved it.
You have to either use application.properties OR a java class for MongoDB configuration.

grails spring security CAS: cannot get login to work with non-local user

My grails 2.5.0 app uses Spring Security with the ldap and cas plugins. I trust this CAS server, so I need to allow users with no local (User, Role, UserRole tables) records to authenticate.
If I have a local user, everything works great. If I don't have a local user, then I get the CAS re-direct error followed by "Sorry, we were not able to find a user with that username and password." I read that the GormUserDetailsService supplied with CAS doesn't work for non-local users, so I've written my own MyUserDetailsService that implements GrailsUserDetailsService, and I've registered it in ./conf/spring/resources.groovy:
beans = {
userDetailsService(edu.uga.reg.MyUserDetailsService)
}
Unfortunately, this doesn't solve the problem: it works with local users, but gives the same re-direct+user not found error if the user isn't in my local database. Here's MyUserDetailService code:
import grails.plugin.springsecurity.SpringSecurityUtils
import grails.plugin.springsecurity.userdetails.GrailsUser
import grails.plugin.springsecurity.userdetails.GrailsUserDetailsService
import grails.transaction.Transactional
import org.springframework.security.core.authority.GrantedAuthorityImpl
import edu.uga.reg.User
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UsernameNotFoundException
class MyUserDetailsService implements GrailsUserDetailsService {
/**
* Some Spring Security classes (e.g. RoleHierarchyVoter) expect at least
* one role, so we give a user with no granted roles this one which gets
* past that restriction but doesn't grant anything.
*/
static final List NO_ROLES =
[new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]
UserDetails loadUserByUsername(String username, boolean loadRoles)
throws UsernameNotFoundException {
return loadUserByUsername(username)
}
UserDetails loadUserByUsername(String username) {
def user = User.findByUsername(username)
// No local user in my db: create one from this username
if (!user)
return new GrailsUser(username, '', true, true, true, NO_ROLES, 999)
def authorities = user.authorities.collect {
new GrantedAuthorityImpl(it.authority)
}
return new GrailsUser(user.username, user.password,
user.enabled, !user.accountExpired, !user.passwordExpired,
!user.accountLocked, authorities ?: NO_ROLES, user.id)
}
}
Here are my cas settings in Config.groovy:
grails.plugin.springsecurity.providerNames = ['casAuthenticationProvider']
grails.plugin.springsecurity.useCAS = true
grails.plugin.springsecurity.cas.active = true
grails.plugin.springsecurity.cas.loginUri = '/login'
grails.plugin.springsecurity.cas.serverUrlPrefix = 'https://cas.dev.server/cas'
grails.plugin.springsecurity.cas.serviceUrl = 'https://apps-dev.server:8743/CASIS/j_spring_cas_security_check'
grails.plugin.springsecurity.logout.afterLogoutUrl = 'https://cas.dev.server/cas/logout?url=http://apps-dev.server:8743/CASIS/'
//default cas settings
grails.plugin.springsecurity.cas.sendRenew = false
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.useSingleSignout = true
grails.plugin.springsecurity.cas.serverUrlEncoding = 'UTF-8'
grails.plugin.springsecurity.cas.proxyCallbackUrl = null
grails.plugin.springsecurity.cas.proxyReceptorUrl = null
Again, CAS works fine if the user is in my local db, but fails otherwise. What am I missing? Thanks.
The answer to my problem is trivial. It's always a good idea to pass the correct number of arguments to the constructor. Instead of:
return new GrailsUser(username, '', true, true, true, NO_ROLES, 999)
I simply needed:
return new GrailsUser(username, '', true, true, true, true, NO_ROLES, 999)
And my user is setup as the principal!

Grails session attributes are not flushed between two applications

I have two separate Grails applications that use the JASIG CAS Client Plugin. When my applications run, different users can authenticate against my CAS server (using the client plugin).
Authentication aside, I use a Grails Filter for authorization in both applications. A user may be authenticated, but I want to make sure that only certain users can only access the appropriate application.
Everything works, except for the below scenario:
I successfully authenticate against the CAS server with username "jack" and I am authorized to use Application A.
I close Application A and sign out of CAS.
I successfully authenticate against the CAS server with username "jill", but I am not authorized to use the Application B because the username from the session is still "jack"
Do I need to flush the session at any point when my applications initiate? If so, how can I do that? Here is the code for my Filter:
import edu.yale.its.tp.cas.client.filter.CASFilter
class SecurityFilters {
def filters = {
loginCheck(controller: '*', action: '*') {
before = {
def username = session?.getAttribute(CASFilter.CAS_FILTER_USER)?.toLowerCase()
if (username in grailsApplication.config.users) {
return true
} else {
render view: '/invalid_user', model: [username: username]
return false
}
}
}
}
}

Resources