Unable to connect to openstack with user which is a domain admin - openstack

I want to do CRUD operations in a domain using domain admin user. I created a user(u1) in a domain(d1). I gave domain admin access to this user. I created a project(p2) and tried to authenticate with user u1 using the following steps:
opts := gophercloud.AuthOptions{
IdentityEndpoint: "EndpointURL",
Username: "u1",
Password: "test",
DomainID: "<DomainID>",
TenantName: "p2",
Scope: &gophercloud.AuthScope{ProjectName: "p2", DomainID: "<DomainID>"},
AllowReauth: true,
}
fmt.Printf("%+v\n", opts)
provider, err := openstack.AuthenticatedClient(opts)
I get "Authentication Failed" Error every time. I also tried with different options ( like omitting scopes, tenantName ... ), but i get the same error all the time. Can you please let me know what i am missing.
I have created openstack(11.0.0) setup using kolla-ansible (all-in-one deployment) in a ubuntu VM.

Related

How do you get IAM credentials using Amplify Auth?

I am trying to get IAM credentials using Amplify ^5.0.7. I am able to successfully log in and get OpenID tokens:
Auth.signIn({
username: user,
password: password
})
.then((u: CognitoUser) => {
console.log("User", u);
console.log("Credentials", Auth.Credentials);
console.log("Essential credentials", Auth.essentialCredentials(Auth.Credentials));
return Auth.currentSession();
}).then((data: CognitoUserSession) => {
console.log("Current session", data);
return Auth.essentialCredentials(Auth.currentCredentials())
}).then((c: ICredentials) => {
console.log("Credentials", c);
})
That successfully signs in, and gets a current session that has id, access, and refresh tokens. The problem is that there are no Credentials. currentCredentials() returns an ICredentials object, but its fields are all undefined. I think those should map to temporary IAM credentials.
The user I'm testing against belongs to exactly one group, and that group has an IAM role assigned to it.
Am I missing a step to request the temporary IAM credentials? I am not using amplify on the backend. I'm really using Amplify Auth because it deals with SRP for me.
I think I figured it out, and it was simpler than I thought. I want to post what I did to fix it, in case anybody else has the same problem.
What I did was basically correct, except you don't need to get the session first.
Auth.signIn({
username: userInput,
password: passwordInput
})
.then((u: CognitoUser) => {
console.log("Auth.credentials", Auth.Credentials)
return Auth.currentCredentials()
}).then((currentCredentials: ICredentials) => {
console.log("Essential credentials", Auth.essentialCredentials(currentCredentials))
})
There was not really a "code" trick to getting it to work. The real problem was that I was not careful enough about how I was setting up Cognito. To do this, you need both a user pool AND an identity pool. The identity pool points back toward the user pool. I had done that, but I wasn't setting Amplify up correctly. The way that works is:
Amplify.configure({
Auth: {
mandatorySignIn: true,
region: 'us-east-1',
userPoolId: 'us-east-1_CX1xxxxxx',
userPoolWebClientId: '5eo394ojo1gvdm6cbxxxxxxxxxs',
identityPoolId: 'us-east-1:f69259b2-ff84-4731-b80c-xf421-xxxx'
}
});
if you don't care about the IAM credentials, you don't seem to need the identity pool nor do you need to specify its ID. If you leave them out, you just get an empty Credentials back.
So Amplify does everything. I'm new to Amplify, and it's a lot less work then dealing with SRP directly.

How can I solve create account problem with different providers?

I have a sign in with Google:example#gmail.com
then create an account with the same email:example#gmail.com
There is a problem with two different providers
Sign in with Google (same Gmail)
Sign in with Email (same Gmail)
How Can I handle these two (When I delete the google sign-in account from Firebase Console. I can create an account with that email) Otherwise I can't create an account with that email and also can't sign in.
I learning Firebase Auth with https://github.com/gladly-team/next-firebase-auth
If you first sign in with Google using "example#gmail.com", it means a user will be created using this particular email address. If you try to sign in with any other provider or with an email and password using the same email address, you'll get an error message that says that the user already exists. And it makes sense since you have already used that email for a user before.
There are two ways in which you can solve this problem. When you get such an error, you can check the provider used to create the account, and notify the user to use it. For example, if the user signs in with Google and tries to authenticate with email and password right after that, display a message to the user in which you should say that the user already exists, and should use the authentication provider which was selected to create the account in the first place, in this case, Google.
The second option would be to allow the user to have multiple accounts using the same email address with different authentication providers. This option can be enabled directly in the Firebase Console, in the Authentication section.
So it's up to you to decide which option works better for your project.
The simple Solution is to enable multiple account an email.
Or ----------------
You Link the account.
This is an example when there is a facebook account with a certain email
and you want to use that same email to sign in with Email and password or gmail, if those two emails are not linked different provider error will be thrown. check here for more
export function linkFaceBookAccount(authContext?: AuthContextType, notificationContext?: NotificationContextType, history?: History.History) {
const provider = new FacebookAuthProvider(); // create a provider
linkWithPopup(auth.currentUser as User, provider).then((result) => {
// This gives you a Google Access Token. You can use it to access the Google API.
// const credential = FacebookAuthProvider.credentialFromResult(result);
// const token = credential?.accessToken;
// The signed-in user info.
const user = result.user;
saveUserToLocalStorage(user);
authContext?.loadUserToState(user);
notificationContext?.addNotification({
message: `This email's (${auth.currentUser?.email}) account has been successful linked with your facebook account`,
title: "Link successful",
notificationType: "SUCCESS",
positiveActionText: "continue",
positiveAction: () => {
history?.push("/")
}
})
}).catch((error) => {
const email = error.customData?.email;
const errorCode = error.code;
const duplicateAccount = errorCode === "auth/account-exists-with-different-credential";
notificationContext?.addNotification({
message: errorFirebase(error, email),
title: "Linking Error",
notificationType: "WARNING",
positiveActionText: duplicateAccount ? "Link" : "ok",
negativeActionText: duplicateAccount ? "cancel" : undefined,
code: errorCode,
positiveAction: () => {
if (duplicateAccount) {
duplicateAccountLinking(email, "FACEBOOK", history);
}
}
})
});}

Microsoft Graph API userInfo endpoint UnknownError: Token must contain sub claim

I'm trying to execute the userinfo endpoint at https://graph.microsoft.com/oidc/userinfo using an access token received through Open ID Connect.
The response received is:
400 Bad Request
{
"error": {
"code": "UnknownError",
"message": "Token must contain sub claim.",
"innerError": {
"date": "2021-02-22T07:14:37",
"request-id": "650a2928-b0e7-49ae-9e6d-ecb569ee69e6",
"client-request-id": "650a2928-b0e7-49ae-9e6d-ecb569ee69e6"
}
}
}
The access token is valid and does contain a sub claim.
If I sign-in to https://developer.microsoft.com/en-us/graph/graph-explorer, and use the access token it automatically retrieves, it works - for the same user. The sub claim is different though and there are two of them.
It seems the token from OIDC doesn't have a correct sub claim - how come might this be?
Access token from directly from the /authorize endpoint [WORKING]:
Access token from OIDC [NOT WORKING]:
OIDC configuration:
options.Authority = authority;
options.ClientId = Configuration[ConfigKeys.IdentityProvider.ClientID];
options.ClientSecret = Configuration[ConfigKeys.IdentityProvider.ClientSecret];
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.CallbackPath = Configuration[ConfigKeys.IdentityProvider.CallbackPath];
options.SignOutScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.CorrelationCookie.Expiration
= options.NonceCookie.Expiration
= options.ProtocolValidator.NonceLifetime
= options.RemoteAuthenticationTimeout
= TimeSpan.FromHours(8);
options.Resource = "https://graph.microsoft.com";
options.GetClaimsFromUserInfoEndpoint = false;
options.UseTokenLifetime = true;
options.RequireHttpsMetadata = true;
options.SaveTokens = true;
options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.Scope.Add("offline_access");
options.Scope.Add("groups");
options.RemoteAuthenticationTimeout = TimeSpan.FromHours(10);
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = authority,
//NameClaimType = "name"
};
The access token is valid and does contain a sub claim.
I suppose you didn't get the token correctly, please follow the steps below.
1.Register an application with Azure AD
2.In the API permissions of the AD App, add the following permission in Microsoft Graph
3.In the Authentication, choose the options below.
4.Hit the URL below in the browser, replace the <tenant-id>, <client-id> of yours, login your user account, then you will get an access_token and an id_token.
https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/authorize?client_id=<client-id>&response_type=token+id_token&redirect_uri=http://localhost&scope=user.read+openid+profile+email&response_mode=fragment&state=12345&nonce=678910
5.Use the access_token to call the https://graph.microsoft.com/oidc/userinfo endpoint, it works fine, the sub value is EY4uO7uc1IG2n8EboEalB4LDxJ1NU8nuc2JXZgkisN4 in my sample.
6.Decode the id_token got in step 4 in https://jwt.io/, the sub is also EY4uO7uc1IG2n8EboEalB4LDxJ1NU8nuc2JXZgkisN4, so it means the sub got from https://graph.microsoft.com/oidc/userinfo endpoint is correct.
If I sign-in to https://developer.microsoft.com/en-us/graph/graph-explorer, and use the access token it automatically retrieves, it works - for the same user. The sub claim is different though and there are two of them.
The token you got from Microsoft Graph Explorer is an access_token, the first sub is the value for access_token, the second one is that you want i.e. sub of id_token.
It seems the token from OIDC doesn't have a correct sub claim - how come might this be?
It is correct, as I mentioned above, the sub you got from the OIDC is the same as the sub got from the id_token.
Reference - https://learn.microsoft.com/en-us/azure/active-directory/develop/userinfo#userinfo-response
These are the same values that the app would see in the ID token issued to the app.
Note: You may find the sub got manually is different from the second sub got from the MS Graph Explorer, this is because your user account logged in two different clients, one is the client of Graph Explorer, another one is your custom AD App.
Reference - https://learn.microsoft.com/en-us/azure/active-directory/develop/id-tokens
Update:
OIDC does not use the v2.0 endpoint, to solve this issue, we need to configure OIDC to make it use the v2.0 endpoint, just add v2.0 in the authority of the configuration.

Realm cloud - global realm

I am really excited about Realm Cloud and started building an app in my beta account.
I have my realm URL's like this:
static let MY_INSTANCE_ADDRESS = "myInstance.us1.cloud.realm.io" // <- update this
static let AUTH_URL = URL(string: "https://\(MY_INSTANCE_ADDRESS)")!
static let REALM_URL = URL(string: "realms://\(MY_INSTANCE_ADDRESS)/users")!
Then I log a user in like this:
let credentials = SyncCredentials.usernamePassword(username: self.userName.field.text ?? "", password: self.password.field.text ?? "", register: true)
SyncUser.logIn(with: credentials, server: RealmConstants.AUTH_URL) { (_, error) in
}
I log in and I see the user created successfully. However, I can not interact with the global realm. I understand this is by design in the latest ROS I would like to see a clear code example how to allow a new user access to the global realm.

Is email authentication using id token possible?

I'm creating a POC for an iOS application that uses extension. The extension has to know if a user is authenticated. Unfortunately a containing app and an extension are separate application which means I have to keep auth state somewhere.
I don't want to store user email and password but instead a token and use it to authenticate. However trying to authenticate with the issued token and providerId (Firebase) does seems to work.
Both apps under the same Firebase project.
Main Application (Firebase ios App1):
let userDefatuls = UserDefaults(suiteName: "group.test")
userDefatuls?.set(providerId!, forKey: "providerId")
userDefatuls?.set(value!, forKey: "token")
print("Saved value to user defaults \(value!)")
userDefatuls?.synchronize()
Extension Application (Firebase ios App2):
let userDefaults = UserDefaults(suiteName: "group.test")
let token = userDefaults?.string(forKey: "token")
let providerId = userDefaults?.string(forKey: "providerId")
print("What is the provider id \(providerId)")
let credential = OAuthProvider.credential(withProviderID: providerId!, accessToken: token!)
Auth.auth().signIn(with: credential) { (user, error) in
print("********* What is the user \(user) what is the error \(error)")
}
The above renders:
What is the user nil what is the error:
Optional(Error Domain=FIRAuthErrorDomain Code=17999 "An internal error has occurred, print and inspect the error details for more information." UserInfo={error_name=ERROR_INTERNAL_ERROR, NSLocalizedDescription=An internal error has occurred, print and inspect the error details for more information., NSUnderlyingError=0x600000447290 {Error Domain=FIRAuthInternalErrorDomain Code=3 "(null)" UserInfo={FIRAuthErrorUserInfoDeserializedResponseKey={
code = 400;
errors = (
{
domain = global;
message = "INVALID_PROVIDER_ID : Provider Id is not supported.";
reason = invalid;
}
);
message = "INVALID_PROVIDER_ID : Provider Id is not supported.";
}}}})
Do you know if the support and works? Is there something what I'm doing wrong?
You can't sign in with a Firebase ID token. What you can do is:
Create an endpoint that takes an ID token, verifies it:
https://firebase.google.com/docs/auth/admin/verify-id-tokens
and returns a custom token:
https://firebase.google.com/docs/auth/admin/create-custom-tokens
You then signInWithCustomToken in the extension.
However, this could open a vulnerability as if a short lived ID token is leaked, the attacker can exchange it for a permanent session via that endpoint.
You can only return the custom token if the auth_time on the ID token is recent. This ensure that a recently signed in user can sync their app to with the extension.

Resources