Need to know if I'm missing something... I'm using sfGuardPlugin and trying to get a complex credential to work... and it's not even that complex. I just can't get either AND or OR to work.
"user_a" is set up to have permission "A" in both permissions and group "A" which also has permission "A" assigned to it.
I also have a Permission "B" and a group "B" set up in the same fashion as above... however, I did not assign user_a to these permissions. To be clear: user_a only has A permissions.
Now in security I have the following (where the user needs to either have credential A or B):
dashboard:
credentials: [[A, B]]
Now when I try to have user_a access the dashboard, it fails and redirects to the credentials required page. I tried the same thing with an AND statement and set up user_a with both, using:
dashboard:
credentials: [A, B]
...again, it failed.
Now, when I remove the brackets, and just use one credential, it all works perfectly. It's just when I use them in combination, in any form, that I run into problems.
Furthermore, I have checked if the user has a single credential, using:
echo $user->hasCredential('A');
And it responds as expected: True
But if I assign the user to both A and B and then try either:
echo $user->hasCredential(array('A', 'B'), false);
or
echo $user->hasCredential(array('A', 'B'));
It responds with False.
I'm stumped. What am I missing? I MUST have at least the [[OR]] working. Has anyone else experienced this? Is there a work-around?
EDIT: code snippet in myUser.class:
public function hasCredential($permission_name)
{
//this overrides the default action (hasCredential) and instead of checking
//the user's session, it now checks the database directly.
if (!$this->isAuthenticated()) {
return false;
}
$gu = $this->getGuardUser();
$groups = $gu->getGroups();
$permissions = $gu->getPermissions();
$permission_names = array();
foreach($permissions as $permission) {
$permission_names[] = $permission->getName();
}
foreach($groups as $group) {
$group_permissions = $group->getPermissions();
foreach($group_permissions as $group_permission) {
$permission_names = array_merge($permission_names, array($group_permission->getName()));
}
}
$permission_names = array_unique($permission_names);
return (in_array($permission_name, $permission_names)) ? true : false;
}
EDIT:
The above code snippet is indeed the problem. I tested it without the code snippet and it works as expected. So my next question, is how to tweak the snippet to accommodate instances with AND or OR? Suggestions?
I'm going to close this question, because I have found the problem and I will open a new question as a result of the issue I'm having with the code snippet (which becomes a new question).
Related
I'm trying to implement the code example in this repo:
https://github.com/autodesk-platform-services/aps-simple-viewer-dotnet
While launching in debugging mode, I get an error in the AuthController.cs says:
Could not list models. See the console for more details
I didn't make any significant changes to the original code, I only changed the env vars (client id, secret etc..)
The error is on the below function:
async function setupModelSelection(viewer, selectedUrn) {
const dropdown = document.getElementById('models');
dropdown.innerHTML = '';
try {
const resp = await fetch('/api/models');
if (!resp.ok) {
throw new Error(await resp.text());
}
const models = await resp.json();
dropdown.innerHTML = models.map(model => `<option value=${model.urn} ${model.urn === selectedUrn ? 'selected' : ''}>${model.name}</option>`).join('\n');
dropdown.onchange = () => onModelSelected(viewer, dropdown.value);
if (dropdown.value) {
onModelSelected(viewer, dropdown.value);
}
} catch (err) {
alert('Could not list models. See the console for more details.');
console.error(err);
}
}
I get an access token so my client id and secret are probably correct, I also added the app to the cloud hub, what could be the problem, why the app can't find the projects in the hub?
I can only repeat what AlexAR said - the given sample is not for accessing files from user hubs like ACC/BIM 360 Docs - for that follow this: https://tutorials.autodesk.io/tutorials/hubs-browser/
To address the specific error. One way I can reproduce that is if I set the APS_BUCKET variable to something simple that has likely been used by someone else already, e.g. "mybucket", and so I'll get an error when trying to access the files in it, since it's not my bucket. Bucket names need to be globally unique. If you don't want to come up with a unique name yourself, then just do not declare the APS_BUCKET environment variable and the sample will generate a bucket name for you based on the client id of your app.
Below are the steps i'm following to create a custom audience based remote config condition -
First I created a user property called OEM
I created a dynamic link with utm_source as google-micromax
https://d83j2.app.goo.gl/?link=http://myapp.in&apn=com.myapp.app&utm_source=google-micromax&utm_medium=micromax_device&utm_campaign=promo_google_micromax
I created an OEM-Micromax audience with the condition that the user property OEM contains google-micromax
I then created a remote config condition based on the Micromax audience
I then handle the dynamic link and set the user property to the value returned from the link's utm_source
AppInvite.AppInviteApi.getInvitation(mGoogleApiClient, this, autoLaunchDeepLink)
.setResultCallback(
new ResultCallback<AppInviteInvitationResult>() {
#Override
public void onResult(AppInviteInvitationResult result) {
if (result.getStatus().isSuccess()) {
//First time user
if (StorageHelper.getBooleanObject(StorageHelper.FIRST_TIME_USER, true)) {
Intent intent = result.getInvitationIntent();
String deepLink = AppInviteReferral.getDeepLink(intent);
Uri uri = Uri.parse(deepLink);
String utm_source = uri.getQueryParameter("utm_source");
FirebaseEvents.setUserProperty(utm_source);
StorageHelper.setBooleanObject(StorageHelper.FIRST_TIME_USER, false);
}
FirebaseEvents.logEventInvite(true);
}
}
});
Now, when I fetch the oem_admob_banner_unit_id parameter from remote config, it still returns the Default value instead of the value for the Micromax audience.
What am I doing wrong ?
Not sure if this is related to your issue, but I also could not get an audience-driven remote config to work. (Mine happened to be an audience based on an app event/parameter so it's a little different scenario but maybe similar problem). It finally started working after I forced enough users in the audience by triggering my event repeatedly. Not sure how many it was, probably around 10.
after fetching, you should call
FIRRemoteConfig - (BOOL)activateFetched
Applies Fetched Config data to the Active Config, causing updates to the behavior and appearance
of the app to take effect (depending on how config data is used in the app).
Returns true if there was a Fetched Config, and it was activated.
Returns false if no Fetched Config was found, or the Fetched Config was already activated.
So I've got an question about authentication and have been wondering how other people might handle this situation. I'm currently running an Angular app that is built on a Rails API.
So far for authentication I have a form that does a post to the Rails side which logs the user in and then sends them back to the Angular app on success. Once the cookie is set and the user is logged in, I'm able to access a user.json file which contains all the User information one might expect (Id, username, roles, rights, etc). Since verification all happens on Rails, if the user logs out then this information is removed. So the two states look like so...
Logged in
{
id: 99384,
name: "Username",
url: "//www.test.com/profiles/Username",
timezone: null,
rights: [ ],
roles: [
"admin"
],
}
Logged out
{
error: "You need to login or join before continuing."
}
So far I've seen all these millions of different ways to do auth for Angular, but it seems like nothing fits this type of method. So my question is, since the server is handling all of the verification, is there a way to just check if they user.json file is empty (displaying the error message) and if it is send the Angular app to the Rails login page? Is there really any point messing with Cookies, Tokens, etc when I can base it all on the JSON file?
You are already using cookies - the server is setting them. What you have done is a fairly standard way of doing things.
To check the json file, you can do something like this stub shows in your controller:
app.controller('AppControl', function($scope, $http, $location){
// Get the JSON file.
$http.get('/path/to/json/file')
.then(response){
if(response.data.error){
// redirect to login
$location.path('login');
}
else{
$scope.user = response.data;
// your app code here.
}
})
.catch(function (error){
// unable to reach the json file - handle this.
});
});
Of course, you should really move this out into a service so you can re-use it, and also cache the data, rather than getting the user every time you change route/page, but this gives you a vague idea.
EDIT Example factory:
.factory('User', function( $http ){
// Create a user object - this is ultimately what the factory will return.
// it's a singleton, so there will only ever by one instance of it.
var user = {};
// NOTE: I am assigning the "then" function of the login promise to
// "whenLoggedIn" - your controller code is then very easy to read.
user.whenLoggedIn = $http.get('user.json')
.then(function(response){
// Check to see if there is an error.
if (response.data.error !== undefined) {
// You could be more thorough with this check to determine the
// correct action (examine the error)
user.loggedIn = false;
}
else {
// the user is logged in
user.loggedIn = true;
user.details = response.data;
return user;
}
}).then; // <-- make sure you understand why that .then is there.
return user;
})
Usage in the controller
.controller('ExampleController', function($scope, User){
// It's handy to have the user on the scope - you can use it in your markup
// like I have with ng-show on index.html.
$scope.User = User;
// Do stuff only if the user is loggedin.
// See how neat this is because of the use of the .then function
User.whenLoggedIn( function (user){
console.log(user.details.name + " is logged in");
});
});
Because it's on the scope, we can do this in the html:
<body ng-controller="ExampleController">
<h1 ng-show="User.loggedIn == null">Logging in..</h1>
<h1 ng-show="User.loggedIn == true">Logged in as {{ User.details.name }}</h1>
<h1 ng-show="User.loggedIn == false">Not logged in</h1>
</body>
Here is an example on plunker where this is working.
Note the following:
If the user is/was already logged in, when you inject the service in the future, it won't check the file again. You could create other methods on the service that would re-check the file, and also log the user out, back in, etc. I will leave that up to you.
There are other ways to do this - this is just one possible option!
This might be obvious, but it's always worth saying. You need to primarily handle authentication and security on the server side. The client side is just user experience, and makes sure the user doesn't see confusing or conflicting screens.
I have a web application that contains a REST api that is interacted with by the client application that lives at /. When a user session times out and the client js application makes a request to the REST api, that request will trigger a login event. Once the user logs in the user is then taken to the REST api endpoint which just displays a JSON response. I would like to hard wire the login page to always redirect to /.
Edit 1: I'm using spring-security-core plugin with the openid plugin as well and grails 2.0.4.
Edit 2: So I managed to get a solution working, however its a bit crude and I would like to know if there is a more elegant solution out there.
I created a simple filter in grails-app/conf/LoginRedirectFilters.groovy:
class RedirectLoginFilters {
def filters = {
redirectAfterLogin (uri: '/api/*') {
before = {
if (session["LOGGING_IN"])
redirect uri: "/"
}
after = {
if (session["LOGGING_IN"])
session["LOGGING_IN"] = false
}
}
}
}
And in my auth function inside of OpenIdController.groovy I added the session flag LOGGING_IN:
def auth = {
def config = SpringSecurityUtils.securityConfig
if (springSecurityService.isLoggedIn()) {
redirect uri: config.successHandler.defaultTargetUrl
return
}
session["LOGGING_IN"] = true
.
.
.
This is working properly by only checking if the LOGGING_IN flag is true when an api endpoint is called, and it also kills the flag after one request so it won't interfere with subsequent client api calls. I realize this is pretty convoluted, so if there is a better solution please let me know, thanks!
Why can't you use the same "springSecurityService.isLoggedIn()" inside your filter as well? I'm pretty sure that works as well.
I think I'm misunderstanding exactly what you want to achieve, but if you always want to redirect to '/' after a successful login, just set these properties in your Config.groovy:
grails.plugins.springsecurity.successHandler.alwaysUseDefault = true
grails.plugins.springsecurity.successHandler.defaultTargetUrl = "/"
If you want different behaviour to this, you'll have to flesh out your question.
I am trying to create and iOS app that takes a users credentials and verifies it with the AD server. Is there some built in library in xCode to do that, or is it third party?
Any advice on direction to look would be greatly appreciated.
Thanks
Zach
Ok, so this was the PHP i used to make the connection to the ldap server. i am not 100% sure what is happening here, i got this code from IT Coordinator at my company. I understand all the binding and searching parts, but i dont get the the ldap_set_option part of this whole thing. Anyway after setting it up this way, you can then call the URL of the php script and pass it parameters. take a look at the PHP, and the url example with be below.
<?php
//Connection parameters
$dn = "DC=network,DC=net";
$host = "ldap://ldap.network.com";
$port = 1111
$user = $_GET['user'];
$pass = $_GET['pass'];
//$user = "user#network.net";
//$pass = "pass";
$filter = "memberof";
$keyword = "CN=USSC_ALL,CN=Users,DC=network,DC=net";
$filter = "objectclass";
$keyword = "user";
$filter = "objectcategory";
$keyword = "CN=Person,CN=Schema,CN=Configuration,DC=network,DC=net";
//The real thing with PHP
if (!empty($keyword) and !empty($dn)) {
//Connect to the AD
$adConn = ldap_connect($host, $port) or die("Could not connect!");
//Set protocol verison
ldap_set_option($adConn, LDAP_OPT_PROTOCOL_VERSION, 3) or die ("Could not set ldap protocol1");
//Set referrals... Won't work without this...
ldap_set_option($adConn, LDAP_OPT_REFERRALS, 0) or die ("Could not set ldap protocol2");
//Bind the user
$bd = ldap_bind($adConn, $user, $pass) or die ("Could not bind");
echo $bd;
//End binding
ldap_unbind($adConn);
} else {
echo "<p>No results found!</p>";
}
?>
</body>
</html>
Ok so now all you have to do is pass a username and password to the script and it will return the bind. that will give you either true or false. meaning if it bound successfully it is a correct combination of username and password.
this is how i am calling it:
http://192.268.192.1/ldap.php?user=(username here)&pass=(password here)
This is the approach that i took, and i think it is a very simple answer.
So what I have been able to find out is that i need to use PHP to do this. By creating a php file on the server, i can use built in ldap protocol to take a user name and password to the ldap server for verification. The query should then return true or false. As soon as i get this working ill post my code