Change authorized user in tests - spring-security-test

I want to test access to a method for a group of users with different roles in one test. I am trying to change the logged in user like this:
#Test
void allMenusAuthorizePermissions() throws Exception {
for (User user : ALL_ROLES_USERS) {
Authentication authentication = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), user.getAuthorities());
SecurityContextHolder.clearContext();
SecurityContextHolder.getContext().setAuthentication(authentication);
log.debug("User role: " + user.getAuthorities());
if (user == ADMIN || user == EDITOR) {
perform(get(MenuEditorController.MENU_EDITOR_URL).principal(authentication))
.andExpect(status().isOk());
}else{
perform(get(MenuEditorController.MENU_EDITOR_URL).principal(authentication))
.andExpect(status().isForbidden());
}
}
}
But no matter how hard I try, perform(get (...)) is always performed from the first user from the ALL_ROLES_USERS array. This can be seen from the log:
o.s.s.a.i.a.MethodSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#e74255f0: Principal: +79990200001; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: CLIENT
-the same user in every iteration!
Any idea why this might be happening? Maybe perform(get(...)) is passing the JSESSIONID of the first user? I don't know where to dig anymore

You need to use:
#Test
void allMenusAuthorizePermissions() throws Exception {
for (User user : ALL_ROLES_USERS) {
log.debug("User role: " + user.getAuthorities());
if (user == ADMIN || user == EDITOR) {
// perform(get(MenuEditorController.MENU_EDITOR_URL).with(SecurityMockMvcRequestPostProcessors.user(user.getUsername()).authorities(user.getAuthorities())))
perform(get(MenuEditorController.MENU_EDITOR_URL).with(SecurityMockMvcRequestPostProcessors.user(user)))
.andExpect(status().isOk());
}else{
perform(get(MenuEditorController.MENU_EDITOR_URL).with(SecurityMockMvcRequestPostProcessors.user(user)))
.andExpect(status().isForbidden());
}
}
}
How to Mock the security context in Spring MVC for testing

Related

Password is expired just after user is added to FreeIPA?

I have set up a FreeIPA server. I am facing an issue which is password is expired when a user is first created. So a new user should always set his password when he logs in for the first time which is defined in here. but I don't want this feature.
I am using this library to create or add user in FreeIPA.
So, I connect with FreeIPA like this-
private function getIPA()
{
$host = env('FREEIPA_HOST', 'cloud-host-ipa.com');
$certificate = database_path(env('FREEIPA_CERTIFICATE', 'ca.crt'));
try {
return new \FreeIPA\APIAccess\Main($host, $certificate);
} catch (Exception $e) {
throw new \ErrorException("Error {$e->getCode()}: {$e->getMessage()}");
return false;
}
}
private function getIPAConnection() //Ged authinticated admin IPA connection
{
$ipa = $this->getIPA();
try {
$auth = $ipa->connection()->authenticate(env('FREEIPA_ADMIN_NAME', 'oc-ipa-connector'), env('FREEIPA_ADMIN_PASS', 'ADMIN_PASS'));
if ($auth) {
return $ipa;
} else {
$auth_info = $ipa->connection()->getAuthenticationInfo();
$auth_info = implode(' ', $auth_info);
throw new \ErrorException("\nLogin Failed : {$auth_info}");
//return false;
}
} catch (Exception $e) {
throw new \ErrorException("\nError {$e->getCode()}: {$e->getMessage()}");
//return false;
}
}
Then add a user like this-
$ipa = $this->getIPAConnection();
try {
$new_user_data = array(
'givenname' => $givenname,
'sn' => $sn,
'uid' => $uid,
//'userpassword' => $_POST["userpassword"],
'mail' => $mail,
'mobile' => $phone
);
$add_user = $ipa->user()->add($new_user_data);
if ($add_user) {
return true;
}
} catch (Exception $e) {
throw new \ErrorException("Error {$e->getCode()}: {$e->getMessage()}");
return false;
}
This code works fine and user is added.
Then I am setting password with this code-
$ipa = $this->getIPAConnection();
try {
$user_info = $ipa->user()->get($uid);
if($user_info != false)
{
try {
$new_user_data = array(
'userpassword' => $password,
);
$mod_user = $ipa->user()->modify($uid, $new_user_data);
if ($mod_user) {
return true;
}
else
{
return false;
}
} catch (Exception $e) {
throw new \ErrorException("Error {$e->getCode()}: {$e->getMessage()}");
}
}
} catch (Exception $e) {
throw new \ErrorException("Error {$e->getCode()}: {$e->getMessage()}");
}
Password is also set perfectly. But the set password is expired automatically just after it is set.
I want my users to have this password for at least 1 week. So, I want to disable this feature. Is there any practical way?
Re-
I have created this issue in FreeIPA to provide us with a workaround, but the issue is closed and marked as - Closed: wontfix . So, I wonder if there exists a workaround?
The answer was provided in the link https://www.redhat.com/archives/freeipa-users/2012-June/msg00360.html.
There is a global policy for passwords that you can see from the command below:
[server]$ ipa pwpolicy-show
Group: global_policy
Max lifetime (days): 90
Min lifetime (hours): 1
History size: 0
Character classes: 0
Min length: 8
Max failures: 6
Failure reset interval: 60
Lockout duration: 600
You can create a new policy override for the group to which you are adding the user by running the command:
[server]$ ipa pwpolicy-add sysadmin --minlife=0
Priority: 50
Group: sysadmin
Min lifetime (hours): 0
Priority: 50
Now this policy overrides the global password policy and creates a policy just for the group.
If you want to modify the global policy, you can do the same with the command:
[server]$ ipa pwpolicy-mod global_policy --minlife=0
Group: global_policy
Max lifetime (days): 90
Min lifetime (hours): 0
History size: 0
Character classes: 0
Min length: 8
Max failures: 6
Failure reset interval: 60
Lockout duration: 600
Note the change in Min lifetime(hours) to 0 which causes password to never expire.
After you create the user you need to run this code from a script in the server:
echo -e $PASSWORD\n$PASSWORD\n$PASSWORD | kinit $username
kdestroy
Note that you need to send PASSWORD and username as parameters to the script and execute this script remotely.
See https://www.freeipa.org/page/New_Passwords_Expired - basically FreeIPA have a policy that admin-set passwords are immediately expired. I believe the "password lifetime" then only applies once the user has themselves changed their password.

Missing Roles Claims in the ASP.NET Core 2 and IdentityServer4

I read https://leastprivilege.com/2017/11/15/missing-claims-in-the-asp-net-core-2-openid-connect-handler/ about mapping custom claims with this code line:
options.ClaimActions.MapUniqueJsonKey("website", "website");
I need to map roles and it works until I have just one role like "User".
options.ClaimActions.MapUniqueJsonKey("role", "role");
The problem is when I have more than one role like "User" and "Superadmin"
That code line throws an exception:
InvalidCastException: Cannot cast Newtonsoft.Json.Linq.JArray to Newtonsoft.Json.Linq.JToken.
Anyone has any idea? Am i wrong something or it could be a bug?
There is a discussion of this issue here:
https://github.com/aspnet/Security/issues/1383
and in the same issue a potential solution to your problem with role:
https://github.com/aspnet/Security/issues/1383#issuecomment-361505163 :
oidcOptions.Events = new OpenIdConnectEvents()
{
OnUserInformationReceived = async context =>
{
// IDS4 returns multiple claim values as JSON arrays, which break the authentication handler
if (context.User.TryGetValue(JwtClaimTypes.Role, out JToken role))
{
var claims = new List<Claim>();
if (role.Type != JTokenType.Array) {
claims.Add(new Claim(JwtClaimTypes.Role, (string)role));
}
else {
foreach (var r in role)
claims.Add(new Claim(JwtClaimTypes.Role, (string)r));
}
var id = context.Principal.Identity as ClaimsIdentity;
id.AddClaims(claims);
}
...
}

Basic authentication for Swagger-UI not working correctly

I have setup Swagger within my ASP.NET project using NSwag which works fine but I am attempting to add support for authentication.
My authentication model is a simple username/password that uses OAuth using ApplicationOAuthProvider
The URL I use to login is as below
/token
With the POST parameters:
grant_type=password&username=${username}&password=${password}
Now my swagger setup [in Global.asax] is
app.UseSwaggerUi(typeof(Global).Assembly, new SwaggerUiSettings
{
MiddlewareBasePath = "/swagger",
OAuth2Client = new OAuth2ClientSettings
{
ClientId = "my_auth_id",
//ClientSecret = "bar",
AppName = "my",
//Realm = "my_realm",
//AdditionalQueryStringParameters = { { "foo", "bar" } }
},
DocumentProcessors = {
new SecurityDefinitionAppender("oauth2", new SwaggerSecurityScheme
{
Type = SwaggerSecuritySchemeType.Basic,
Description = "Description is set htere",
Flow = SwaggerOAuth2Flow.Password,
AuthorizationUrl = "https://localhost:28866/token?",
TokenUrl = "https://localhost:28866/token",
In = SwaggerSecurityApiKeyLocation.Query
//Scopes = new Dictionary<string,string>
//{
// //{ "read", "Read access to protected resources" },
// { "write", "Write access to protected resources" }
//}
})
},
OperationProcessors =
{
new OperationSecurityScopeProcessor("oauth2")
}
});
I know its a bit messy but I was literally trying every option I could to make it work.
So this actually gives me the Authorize button and a Username and Password field. But when I click login it refreshes the swagger.json but doesnt actually attempt to log in anywhere?

not getting user id from from Auth::instance->get_user()-id in Kohana

I am using auth module of kohana. I did register and login and its working fine. But when i do Auth::instance()->get_user()->id i get NULL
While login i do it with Auth::instance()->login($validator['email'], $validator['password']) and then redirect user to home page.
But when in one of the controller i do Auth::instance()->get_user()->id i get NULL
What would be the cause. Is that i have to first set something???
Try Auth::instance()->get_user()->pk().
pk() is for primary key.
Works in KO3.
My Mistake
In the _login function of modules/auth/classes/kohana/auth/orm.php
In that i was doing the following
$user = ORM::factory('user');
$user->where('email', ' = ', $email)
->and_where('password', ' = ', $password)
->find();
// TODO remember to be done
if ($user !== null) {
$this->complete_login($user);
return true;
} else {
return false;
}
In above i was checking $user is null or not but if the email and password not match the user instance will be created with NULL values for all the columns.
So now i am checking $user->id !== NULL and it is working fine.
Try this:
if ($user->loaded()) {
$this->complete_login($user);
return true;
} else {
return false;
}
See ORM::__call() if you want to know what happends (since ORM::loaded() does not exist)

Drupal: How to differentiate between new user registration and user password update in hook_user validate operation?

I am using hook_user validate operation to validate user registration info against my business logic.
I want separate logics to run on registration and change password.
But I am unable to differentiate between the two - both pass through validation and same code is run for both.
How can I differentiate between the two inside the validate op in hook_user?
with $form_id
if ( ($form_id == 'user_profile_form' && arg(3) == NULL) {
// validation code for updating
}
elseif ($form_id == 'user_register') ) {
// validation code for registering
}
In Drupal 7 you may try something like:
/**
* Implements hook_form_FORM_ID_alter().
* Form ID: user_profile_form
*/
function foo_form_user_profile_form_alter($form, &$form_state) {
// Set a custom form validate and submit handlers.
$form['#validate'][] = 'foo_form_user_profile_form_validate';
$form['#submit'][] = 'foo_form_user_profile_form_submit';
}
/**
* Implements hook_form_FORM_ID_alter().
* Form ID: user_register_form
*/
function foo_form_user_register_form_alter($form, &$form_state) {
if ($form['#user_category'] == 'account') {
// Set a custom form validate and submit handlers.
$form['#validate'][] = 'foo_form_user_register_validate';
$form['#submit'][] = 'foo_form_user_register_submit';
}
}

Resources