Goodday,
I have an issue with running my code through CI. When I run my code locally the test is fine.
So I have a Role Model (no pun intended)
and in my test i assign the role to a newly created test user.
// Assigning Role
$role = Role::where('name','administrator')->first();
$user->assignRole($role);
The assign Role is added through my User Model
/**
* Assigns Role to the User
*
* #param Role $role
*/
public function assignRole(Role $role)
{
$this->roles()->save($role);
}
When I run the Test locally it works like it was intended.
PASS Tests\Feature\UserTest
✓ user login
✓ users list allowed
✓ users list not allowed
✓ user creation
✓ user delete
Tests: 6 passed
Time: 7.05s
But when i am running it in my CI env. I get the following error message:
✓ basic test
FAIL Tests\Feature\UserTest
✓ user login
✓ users list allowed
✓ users list not allowed
⨯ user creation
✓ user delete
---
• Tests\Feature\UserTest > user creation
TypeError
Argument 1 passed to App\Models\User::assignRole() must be an instance of App\Models\Role, null given, called in /builds/marcel43/backendapi/tests/Feature/UserTest.php on line 86
at app/Models/User.php:73
69▕ * Assigns Role to the User
70▕ *
71▕ * #param Role $role
72▕ */
➜ 73▕ public function assignRole(Role $role)
74▕ {
75▕ $this->roles()->save($role);
76▕ }
77▕
1 tests/Feature/UserTest.php:86
App\Models\User::assignRole()
Tests: 1 failed, 5 passed
Time: 0.97s
What am i missing here?
I have mad an whoopsie on my database seeding, i created the seeder but did not add it to the database. That's why it could not find the role.
Related
We use WSO2 5.10.1 for SSO and I am trying to get adaptive MFA working but having some trouble. The IP-based adaptive authentication template works, but for some reason, the role-based template does not. For some reason, the variable hasRole always returns false, even though my test user is a member of the internal role called staff2. staff2 is an internal role containing only the test user.
The wso2carbon.log with the info is below. I also included the script I am using, which is the default role-based template PLUS a few modifications I made to get a little more information in the log.
Log:
TID: [-1234] [] [2021-02-02 10:14:34,684] [badcbf3d-288c-4d3a-8abc-372763d87e0b] INFO {org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsLogger} - Working so far
TID: [-1234] [] [2021-02-02 10:14:34,684] [badcbf3d-288c-4d3a-8abc-372763d87e0b] INFO {org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsLogger} - false string info
TID: [-1234] [] [2021-02-02 10:14:34,684] [badcbf3d-288c-4d3a-8abc-372763d87e0b] INFO {org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsLogger} - <testuser> Has one of Roles: [staff2]
My Code:
// Role-Based from Template...
// This script will step up authentication for any user belonging
// to one of the given roles
// If the user has any of the below roles, authentication will be stepped up
var rolesToStepUp = ['staff2'];
var onLoginRequest = function(context) {
executeStep(1, {
onSuccess: function (context) {
// Extracting authenticated subject from the first step
var user = context.currentKnownSubject;
// Checking if the user is assigned to one of the given roles
var hasRole = hasAnyOfTheRoles(user, rolesToStepUp);
Log.info('Working so far');
Log.info(hasRole + ' string info');
if (5 > 1) {
Log.info(user.username + ' Has one of Roles: ' + rolesToStepUp.toString());
executeStep(2);
}
}
});
};
// End of Role-Based.......
Change your rolesToStepUp variable as follows and try out.
var rolesToStepUp = ['Internal/staff2'];
If you use the variable as var rolesToStepUp = ['staff2'];, it checks whether the user has a role named 'staff2' in the PRIMARY userstore. For example, if you create a Role by selection domain- PRIMARY and role name- staff2, the user who gets assigned to that role will be able to go through 2 steps according to your script.
If you want to use a role other than a role attached to PRIMARY userstore, you need to define the domain in the var rolesToStepUp array.
Since you have created an internal role, var rolesToStepUp should be defined as var rolesToStepUp = ['Internal/staff2'];
I have a service account with domain wide delegation setup and I'm trying to create new accounts(google-api-services-admin-directory) using the service account and then add some preset calendars(google-api-services-calendar) to the newly created accounts.
I've had no problems with the directory api. I've had to create a delegated (Admin) User using the service account and all the directory-api calls work fine.
However, I've been having trouble in getting the calendar-api calls to work.
Java dependencies:
compile group: 'com.google.auth', name: 'google-auth-library-oauth2-http', version:'0.20.0'
compile group: 'com.google.apis', name: 'google-api-services-admin-directory', version:'directory_v1-rev53-1.20.0'
compile group: 'com.google.apis', name: 'google-api-services-calendar', version:'v3-rev20200315-1.30.9'
Java code:
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static final List<String> SCOPES =
Arrays.asList(DirectoryScopes.ADMIN_DIRECTORY_USER, DirectoryScopes.ADMIN_DIRECTORY_GROUP,
CalendarScopes.CALENDAR);
private static final String CREDENTIALS_FILE_PATH = "config/google-service-account-credentials.json";
.....
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
sourceCredentials =
ServiceAccountCredentials.fromStream(new FileInputStream(CREDENTIALS_FILE_PATH));
sourceCredentials = (ServiceAccountCredentials) sourceCredentials.createScoped(SCOPES);
.....
GoogleCredentials targetCredentials = sourceCredentials.createDelegated("newuser#email");
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(targetCredentials);
targetCredentials.refreshIfExpired();//Not sure if this is required. It didn't help though
Calendar calendarService = new Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer).setApplicationName(MainApp.SERVICE_NAME).build();
for (String calendarKey : listOfCalendars)) {
CalendarListEntry cle = new CalendarListEntry();
cle.setId(calendarKey);
calendarService.calendarList().insert(cle).execute();//Fails with a 401
}
Stack Trace :
Caused by: java.io.IOException: Error getting access token for service account: 401 Unauthorized
at com.google.auth.oauth2.ServiceAccountCredentials.refreshAccessToken(ServiceAccountCredentials.java:444)
at com.google.auth.oauth2.OAuth2Credentials.refresh(OAuth2Credentials.java:157)
at com.google.auth.oauth2.OAuth2Credentials.refreshIfExpired(OAuth2Credentials.java:174)
at myApp.GSuiteSDKHelper.updateDefaultCalendars(GSuiteSDKHelper.java:169)
... 65 more
Caused by: com.google.api.client.http.HttpResponseException: 401 Unauthorized
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1113)
at com.google.auth.oauth2.ServiceAccountCredentials.refreshAccessToken(ServiceAccountCredentials.java:441)
... 68 mo
And the interesting part is that the error is intermittent. After a redeploy, I can always get my first attempt to work. Following that, it is a hit or miss.
I did add the service account to the calendars that I'm trying to add and also ensure the service account is an "owner" on the calendars.
Something similar happened to me, in my case I could solve it by adding the scopes: "https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/userinfo.profile"
I am using Parse Server from the market place of AWS and is able to access the database without a problem. But, I am not able to send email verification to newly signed up users.
After did some research, I know that I have to add Mail Adapter and enable a few parameters for the Parse Server but I don't know how to add Adapter from the dashboard
https://github.com/parse-community/parse-server#email-verification-and-password-reset
It's not possible to add a mail adapter using the dashboard. You should have the Mailgun adapter installed by default.
To add the configuration you need to access your server and add the following to your index.js file:
var server = ParseServer({
...otherOptions,
// Enable email verification
verifyUserEmails: true,
// if `verifyUserEmails` is `true` and
// if `emailVerifyTokenValidityDuration` is `undefined` then
// email verify token never expires
// else
// email verify token expires after `emailVerifyTokenValidityDuration`
//
// `emailVerifyTokenValidityDuration` defaults to `undefined`
//
// email verify token below expires in 2 hours (= 2 * 60 * 60 == 7200 seconds)
emailVerifyTokenValidityDuration: 2 * 60 * 60, // in seconds (2 hours = 7200 seconds)
// set preventLoginWithUnverifiedEmail to false to allow user to login without verifying their email
// set preventLoginWithUnverifiedEmail to true to prevent user from login if their email is not verified
preventLoginWithUnverifiedEmail: false, // defaults to false
// The public URL of your app.
// This will appear in the link that is used to verify email addresses and reset passwords.
// Set the mount path as it is in serverURL
publicServerURL: 'https://example.com/parse',
// Your apps name. This will appear in the subject and body of the emails that are sent.
appName: 'Parse App',
// The email adapter
emailAdapter: {
module: '#parse/simple-mailgun-adapter',
options: {
// The address that your emails come from
fromAddress: 'parse#example.com',
// Your domain from mailgun.com
domain: 'example.com',
// Your API key from mailgun.com
apiKey: 'key-mykey',
}
},
// account lockout policy setting (OPTIONAL) - defaults to undefined
// if the account lockout policy is set and there are more than `threshold` number of failed login attempts then the `login` api call returns error code `Parse.Error.OBJECT_NOT_FOUND` with error message `Your account is locked due to multiple failed login attempts. Please try again after <duration> minute(s)`. After `duration` minutes of no login attempts, the application will allow the user to try login again.
accountLockout: {
duration: 5, // duration policy setting determines the number of minutes that a locked-out account remains locked out before automatically becoming unlocked. Set it to a value greater than 0 and less than 100000.
threshold: 3, // threshold policy setting determines the number of failed sign-in attempts that will cause a user account to be locked. Set it to an integer value greater than 0 and less than 1000.
},
// optional settings to enforce password policies
passwordPolicy: {
// Two optional settings to enforce strong passwords. Either one or both can be specified.
// If both are specified, both checks must pass to accept the password
// 1. a RegExp object or a regex string representing the pattern to enforce
validatorPattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.{8,})/, // enforce password with at least 8 char with at least 1 lower case, 1 upper case and 1 digit
// 2. a callback function to be invoked to validate the password
validatorCallback: (password) => { return validatePassword(password) },
validationError: 'Password must contain at least 1 digit.' // optional error message to be sent instead of the default "Password does not meet the Password Policy requirements." message.
doNotAllowUsername: true, // optional setting to disallow username in passwords
maxPasswordAge: 90, // optional setting in days for password expiry. Login fails if user does not reset the password within this period after signup/last reset.
maxPasswordHistory: 5, // optional setting to prevent reuse of previous n passwords. Maximum value that can be specified is 20. Not specifying it or specifying 0 will not enforce history.
//optional setting to set a validity duration for password reset links (in seconds)
resetTokenValidityDuration: 24*60*60, // expire after 24 hours
}
});
You will need to replace some of the values with your own. See here for more details.
I want to make testing endpoints in a Google App Engine instance easier by using a script. Based on this information https://webapp-improved.appspot.com/guide/testing.html, I wrote a simple script like this:
from main import app
params = {
'top': 'true',
'sort_by': 'most-recent',
}
query = urllib.urlencode(params)
url = '/activities?' + query
request = webapp2.Request.blank(url)
response = request.get_response(app)
But there is a problem: my handler has a security check to ensure only signed-in user can call the endpoint. It will return status code of 401 (HTTPUnauthorized) if the cookie __auth__ is not set propertly
HTTPUnauthorized: This server could not verify that you are authorized to access the document you requested. Either you supplied the wrong credentials (e.g., bad password), or your browser does not understand how to supply the credentials required.
Here is the relevant webapp2 configuration
'webapp2_extras.sessions': {
'cookie_name': '__session__',
'secret_key': login.secrets.SESSION_KEY,
'cookie_args': {
'max_age': 30 * 24 * 60 * 60
}
},
'webapp2_extras.auth': {
'cookie_name': '__auth__',
# Use with 'remember' flag to make persistent cookies
'token_max_age': 30 * 24 * 60 * 60,
'user_attributes': []
},
I have tried to 'monkey-patch' my handler classes to bypass the check.
Here is the get function of my handler class ActivitiesHandler (it extends webapp2.RequestHandler)
def get(self):
# Checking if user is logged in
if self.secure and not self.logged_in:
self.abort(401)
# ...
My money patch code goes like this:
ActivitiesHandler.secure = False
However it does not take any effect. I think it is because the app variable, being a variable of a module scope, is already initialised along with all the handlers well before my money patch code is executed.
As an alternative, I want to programmatically create a __auth__ for a valid User entity. But I cannot find relevant information regarding this.
Any pointer or sample code will be welcome.
I have this shiro.ini:
[main]
ds = org.apache.shiro.jndi.JndiObjectFactory
ds.requiredType = javax.sql.DataSource
ds.resourceName = java:/comp/env/jdbc/myDS
# JDBC realm config
jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.permissionsLookupEnabled = true
jdbcRealm.authenticationQuery = "SELECT password FROM user WHERE username = ?"
jdbcRealm.dataSource = $ds
credentialsMatcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
# base64 encoding, not hex in this example:
credentialsMatcher.storedCredentialsHexEncoded = false
credentialsMatcher.hashIterations = 1024
jdbcRealm.credentialsMatcher = $credentialsMatcher
[urls]
/logout = logout
/** = authcBasic
Im debbuging JndiRealm in doGetAuthenticationInfo. I get an exception when shiro try to execute my authenticationQuery in getPasswordForUser method. Those are the lines that execute the select:
ps = conn.prepareStatement(authenticationQuery);
ps.setString(1, username);
My atuthenticationQuery is "SELECT password FROM user WHERE username = ?" so trying to access position 1 is invalid since it starts from position 0. Is that a bug on JndiRealm from apache shiro or i wrote my sql wrong?
Looks like you have a simple mock implementation of a realm.
For logging in to work, you needs 2 steps:
authentication (is the username/password correct)
authorization (what is the user allowed to do)
Looks like you have only created the first step, but you are just giving back the password in the return statement.
Shiro will hash the password that was entered by the user. You should have the same hash stored somewhere in your database. In the doGetAuthenticationInfo you should do a lookup based on the username that was entered and retrieve the hash (either from the db, or disk or whatever you prefer), that is what you should put in the SimpleAuthenticationInfo object and return, shiro will do the user password hashing and comparison for you.
For the second step, override the method doGetAuthorizationInfo. You could let it return an instance of SimpleAuthorixationInfo containg a set of permissions, the simplest being "*", when it has access to everything.
Creating such a method can be as simple as:
#Override
public AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//here you can create custom permissions based on the principal
//that has been authenticated using your own logic
info.addStringPermission("*");
return info;
}