I can add users to keycloak but only in the master realm. Is there a way to add users to other realms beside master?
I tried and received an HTTP 401 Unauthorized Exception.
Sounds like your user doesn't have the manage-users role in other realms.
Just go to the admin realm, look up your user, navigate to Role mappings tab, then in the Client Roles drop down select the correct realm and then add manage-users as a role. Repeat for all realms.
//Here's how I created a user to my realm using Java
#Override
public UserDto registerNewUserAccount(final UserDto accountDto) {
String keycloakPassword = accountDto.getPassword();
accountDto.setPassword(passwordEncoder.encode(accountDto.getPassword()));
accountDto.setEnabled(1);
UserDto user = userRepository.save(accountDto);
AuthorityDto role = new AuthorityDto();
role.setUserName(accountDto.getLogin());
role.setAuthority("ROLE_USER");
authorityRepository.save(role);
Keycloak kc = Keycloak.getInstance(
"https://www.zdslogic.com/keycloak/auth", /your server
"zdslogic", //your realm
"richard.campion", //user
"Changit", //password
"admin-cli"); //client
CredentialRepresentation credential = new CredentialRepresentation();
credential.setType(CredentialRepresentation.PASSWORD);
credential.setValue(keycloakPassword);
UserRepresentation keycloakUser = new UserRepresentation();
keycloakUser.setUsername(accountDto.getLogin());
keycloakUser.setFirstName(accountDto.getFirstName());
keycloakUser.setLastName(accountDto.getLastName());
keycloakUser.setEmail(accountDto.getEmail());
keycloakUser.setCredentials(Arrays.asList(credential));
keycloakUser.setEnabled(true);
keycloakUser.setRealmRoles(Arrays.asList("user"));
// Get realm
RealmResource realmResource = kc.realm("zdslogic");
UsersResource usersRessource = realmResource.users();
// Create Keycloak user
Response result = null;
try {
result = usersRessource.create(keycloakUser);
} catch(Exception e) {
System.out.println(e);
}
if (result==null || result.getStatus() != 201) {
System.err.println("Couldn't create Keycloak user.");
}else{
System.out.println("Keycloak user created.... verify in keycloak!");
}
return user;
}
Related
We have Xamarin forms app integrated with azure authentication using MSAL. When we log out we are removing the accounts from the PCA and the code was executed without having any issue. But on the subsequent login, it is getting authenticated without even entering the credentials. It is logging in with previously entered credentials. Looks like the cache is not getting cleared properly.
private async void AuthenticateUser()
{
App.Scopes = new string[] { "<client_id>" + "/.default" };
var redirectUri = "msal<clientId>" + "://auth";
if (Device.RuntimePlatform == Device.iOS)
{
App.PCA = PublicClientApplicationBuilder.Create("<client_id>")
.WithIosKeychainSecurityGroup("<package_name>")
.WithRedirectUri(redirectUri)
.Build();
}
else
{
App.PCA = PublicClientApplicationBuilder
.Create(CommonHelper.ClientId)
.WithRedirectUri(redirectUri)
.Build();
}
var accounts = await App.PCA.GetAccountsAsync();
var uid = new UserIdentifier("<user_name>", UserIdentifierType.OptionalDisplayableId);
AuthenticationResult authResult;
try
{
while (accounts.Any())
{
await App.PCA.RemoveAsync(accounts.First());
accounts = (await App.PCA.GetAccountsAsync()).ToList();
}
var firstAccount = accounts.FirstOrDefault();
authResult = await App.PCA.AcquireTokenSilent(App.Scopes, firstAccount)
.ExecuteAsync();
ProceedToLogin(authResult.AccessToken);
}
catch (MsalUiRequiredException mex)
{
try
{
authResult = await App.PCA.AcquireTokenInteractive(App.Scopes)
.WithParentActivityOrWindow(App.ParentWindow)
.WithLoginHint("<user_name>")
.WithUseEmbeddedWebView(true)
.ExecuteAsync();
ProceedToLogin(authResult.AccessToken);
}
catch (Exception ex)
{
Log(ex);
}
}
}
Please find the code below which will execute during the logout.
public void Logout(string authority)
{
if (App.PCA == null)
{
App.Scopes = new string[] { "<client_id>" + "/.default" };
var redirectUri = "msal<azure_client_id>://auth";
App.PCA = PublicClientApplicationBuilder.Create("<client_id>")
.WithIosKeychainSecurityGroup("<package_name>")
.WithRedirectUri(redirectUri)
.Build();
}
var accounts = App.PCA.GetAccountsAsync().Result;
if (accounts != null)
{
while (accounts.Any())
{
App.PCA.RemoveAsync(accounts.First());
accounts = App.PCA.GetAccountsAsync().Result;
}
}
}
Also, we tried with the below code to clear the cookies. It was working fine in lower versions but again the issue is happening from iOS 14.6 and above.
var cookieStorage = NSHttpCookieStorage.SharedStorage;
foreach (var cookie in cookieStorage.Cookies)
{
cookieStorage.DeleteCookie(cookie);
}
Try adding the following line
.WithPrompt(Prompt.ForceLogin);
Example
PublicClientApplicationBuilder.Create("<client_id>")
.WithIosKeychainSecurityGroup("<package_name>")
.WithRedirectUri(redirectUri)
.WithPrompt(Prompt.ForceLogin);
.Build();
As far as I understand this from my own implementation of MSAL in .NET this is working as expected, I'm not sure how well this carries over to Xamarin. When you log a user out of they will no longer be authenticated against your application, but will keep authentication to Microsoft. When you send an unauthenticated user to the Microsoft endpoint to log back in to your application (as in your screenshot) Microsoft correctly identifies that they are still logged in to their Microsoft account, however that account is not logged in to your application. At this point Microsoft offers the list you see giving the option to use the authenticated account or choose a different one to use sign in to your application.
Their are two levels in play when authenticating against MS, authentication against MS and authentication against your application. Your application can only clear authentication against itself, not Microsoft which lets user stay logged into to other MS services (Outlook etc).
I'm using firebase anonymous authantication for my unity project.
As i always did when project is started i'm sending request to firebase for authantication,
but on my last project (which uses firebase sdk 6.16.0) my request creates new user everytime.
Here is some code about how i'm sending my request
Firebase.Auth.FirebaseAuth auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
auth.SignInAnonymouslyAsync().ContinueWith((task =>
{
if (task.IsCanceled)
{
Debug.Log("task cancelled");
return;
}
if (task.IsFaulted)
{
Debug.Log("task cancelled");
return;
}
if (task.IsCompleted)
{
Firebase.Auth.FirebaseUser userr = task.Result;
firebaseUserId = userr.UserId;
Debug.Log("firebaseUserId");
Debug.Log(firebaseUserId);
//every opening returns new uniq id here.
}
}));
On firebase authantication panel i only activated anonymous login. any suggestions?
Or is there any way to downgrade unity firebase version? i've tried to import old version which i was using on my last game (sdk 6.15.2) but there is some errors on resolver.
Basically, every time you call SignInAnonymouslyAsync you'll create a new user and the last one will be basically lost (it's more or less a random hash - anonymous as it's name suggests).
I'll typically do something like:
using System;
using Firebase.Auth;
using UnityEngine;
using UnityEngine.Events;
public class Login : MonoBehaviour
{
public UnityEvent OnSignInFailed = new UnityEvent();
public UserSignedInEvent OnUserSignedIn = new UserSignedInEvent();
public async void TriggerLogin()
{
var auth = FirebaseAuth.DefaultInstance;
var user = auth.CurrentUser;
if (user == null)
{
try
{
user = await auth.SignInAnonymouslyAsync();
}
catch (Exception e)
{
Debug.LogException(e);
OnSignInFailed.Invoke();
return;
}
}
// user definitely should not be null!
if (user == null)
{
OnSignInFailed.Invoke();
Debug.LogWarning("User still null!?");
return;
}
var userName = user.UserId;
OnUserSignedIn.Invoke(userName);
Debug.Log($"Logged in as {userName}");
}
[Serializable]
public class UserSignedInEvent : UnityEvent<string>
{
}
}
Note that for this code snippet, TriggerLogin is a public method so I can chain it off of a UnityEvent in the Unity editor.
Try and Put it some kind of check to find if used is already logged in. If yes, then do a silent login, if no then use anonymous login.
Currently you are straightaway logging in user even if they logged in last time they opened the Application.
Try this link: https://github.com/firebase/quickstart-unity/issues/266#issuecomment-447981995
Here, I am trying to authenticate user via login and after that I want to skip permissions dialog. But I am unable to achieve this, as it always asking for permissions for app to the user. My intention is if user is not logged into the facebook he/she should be prompted for facebook login and then I will fetch public information by using method Get("/me"). Let me know what I am doing wrong here.
public string GetFBAccessToken(string strAppID, string strAppSecret, string strUrl)
{
// Declaring facebook client type
var vFB = new FacebookClient();
string strAccessTok = string.Empty;
try
{
if (!string.IsNullOrEmpty(strAppID) && !string.IsNullOrEmpty(strAppSecret) && !string.IsNullOrEmpty(strUrl))
{
// Getting login url for facebook
var loginUrl = vFB.GetLoginUrl(new
{
client_id = strAppID,
client_secret = strAppSecret,
redirect_uri = strUrl,
response_type = "code",
state = "returnUrl",
//scope = "",
display = "popup"
});
// Redirecting the page to login url
if (HttpContext.Current.Request.QueryString["code"] == null)
{
HttpContext.Current.Response.Redirect(loginUrl.AbsoluteUri);
}
// Fetching the access token from query string
if (HttpContext.Current.Request.QueryString["code"] != null)
{
dynamic result = vFB.Post("oauth/access_token", new
{
client_id = strAppID,
client_secret = strAppSecret,
redirect_uri = strUrl,
code = HttpContext.Current.Request.QueryString["code"]
});
// Getting access token and storing in a variable
strAccessTok = result.access_token;
}
}
return strAccessTok;
}
catch (Exception ex)
{
//if (HttpContext.Current.Request.QueryString["response_type"] == "code")
//{
// var fb = new FacebookClient();
// var details = fb.Get("/me");
//}
return strAccessTok;
}
}
Regardless to the platform/ language you are using; solution can be as follows.
check use's logged in status. https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus/
based on Response status, forcefully call your action (i.e. Log in, Get Permission or any additional action if user is already connected). For Log in check this reference document from FB. https://developers.facebook.com/docs/facebook-login/login-flow-for-web/
No. You cannot skip the Login Dialog.
In fact, it is really important for an APP owner to build a trust relationship with your users. I would recommend you to follow the Login Best Practices while authenticating the users using your APP.
The opposite of: How to manually log out a user with spring security?
In my app I have register new user screen, which posts to a controller which creates a new user within db (and does a few obvious checks).I then want this new user to be automatically logged in ... I kind of want somethign like this :
SecurityContextHolder.getContext().setPrincipal(MyNewUser);
Edit
Well I have almost implemented based on the answer to How to programmatically log user in with Spring Security 3.1
Authentication auth = new UsernamePasswordAuthenticationToken(MyNewUser, null);
SecurityContextHolder.getContext().setPrincipal(MyNewUser);
However, when deployed the jsp can not access my MyNewUser.getWhateverMethods() whereas it does when normal login procedure followed. the code that works nomrally, but throws an error when logged in like above is below :
<sec:authentication property="principal.firstname" />
In my controller i have this, which logs user in as normal :
Authentication auth =
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(auth);
Where user is my custom user object(implementing UserDetails) that is newly created. The getAuthorities() method does this (just because all my users have the same role):
public Collection<GrantedAuthority> getAuthorities() {
//make everyone ROLE_USER
Collection<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
GrantedAuthority grantedAuthority = new GrantedAuthority() {
//anonymous inner type
public String getAuthority() {
return "ROLE_USER";
}
};
grantedAuthorities.add(grantedAuthority);
return grantedAuthorities;
}
You can also inject your spring security configured UserDetailsManager to your controller and use that to get the UserDetails which holds the principal and authorities to avoid duplicate code:
// inject
#Autowired
private UserDetailsManager manager;
// use in your method
UserDetails userDetails = manager.loadUserByUsername (token.getUsername ());
Authentication auth = new UsernamePasswordAuthenticationToken (userDetails.getUsername (),userDetails.getPassword (),userDetails.getAuthorities ());
SecurityContextHolder.getContext().setAuthentication(auth);
From the spring security source AbstractAuthenticationProcessingFilter:
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
Authentication authResult) throws IOException, ServletException {
if (logger.isDebugEnabled()) {
logger.debug("Authentication success. Updating SecurityContextHolder to contain: " + authResult);
}
// you need this
SecurityContextHolder.getContext().setAuthentication(authResult);
rememberMeServices.loginSuccess(request, response, authResult);
if (this.eventPublisher != null) {
eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
}
successHandler.onAuthenticationSuccess(request, response, authResult);
}
Note however that the SecurityContextHolder is usually cleared upon completion of the filter chain.
For anyone trying to do this with Reactive Spring Security, this is what I did and it seemed to work.
private Mono<Authentication> authenticateUser(ServerWebExchange exchange, UserDetails userDetails,String rawPassword)
{
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userDetails.getUsername(),rawPassword);
return reactiveAuthenticationManager.authenticate(token).filter(auth -> auth.isAuthenticated()).flatMap(auth ->
{
SecurityContextImpl securityContext = new SecurityContextImpl();
securityContext.setAuthentication(auth);
return securityContextRepository.save(exchange,securityContext).then(Mono.just(auth));
});
}
I am using windows Authentication and accessing user name as.
IIdentity winId = HttpContext.Current.User.Identity;
string name = winId.Name;
but i want to get other details like User full name and EmailID.
Since you're on a windows network, then you need to query the Active directory to search for user and then get it's properties such as the email
Here is an example function DisplayUser that given an IIdentity on a windows authenticated network, finds the user's email:
public static void Main() {
DisplayUser(WindowsIdentity.GetCurrent());
Console.ReadKey();
}
public static void DisplayUser(IIdentity id) {
WindowsIdentity winId = id as WindowsIdentity;
if (id == null) {
Console.WriteLine("Identity is not a windows identity");
return;
}
string userInQuestion = winId.Name.Split('\\')[1];
string myDomain = winId.Name.Split('\\')[0]; // this is the domain that the user is in
// the account that this program runs in should be authenticated in there
DirectoryEntry entry = new DirectoryEntry("LDAP://" + myDomain);
DirectorySearcher adSearcher = new DirectorySearcher(entry);
adSearcher.SearchScope = SearchScope.Subtree;
adSearcher.Filter = "(&(objectClass=user)(samaccountname=" + userInQuestion + "))";
SearchResult userObject = adSearcher.FindOne();
if (userObject != null) {
string[] props = new string[] { "title", "mail" };
foreach (string prop in props) {
Console.WriteLine("{0} : {1}", prop, userObject.Properties[prop][0]);
}
}
}
gives this:
Edit: If you get 'bad user/password errors'
The account that the code runs under must have access the users domain. If you run code in asp.net then the web application must be run under an application pool with credentials with domain access. See here for more information
You can define a MyCustomIdentity by overriding from IIdentity and add your own properties etc.
Cast it to the specific Identity, for example WindowsIdentity