I am using custom authenticator, if it fails then basic authenticator will be used for login and on login success I am using another authenticator to set the custom claims and after that a forced reset authenticator to check force password reset incase of password expiry.
But if basic authentor fails the page is redirecting to SAML authenticator failure instead of login page with retry option. So,how to retry login incase of failure and incase of success call Step3 and Step4.
Step1: custom authenticator
Step2: basic authenticator
Step3: local authenticator
Step4: password reset enforcer
var onLoginRequest = function(context) {
executeStep(1,{
onSuccess: function (context) {
},
onFail: function(context){
executeStep(2,{
onSuccess: function (context) {
executeStep(4);
executeStep(3);
},
onFail: function(context){
}
});
}
});
};
Retry from the authenticator itself is suppressed when you enable the adaptive script. This is to give full control for the adaptive script to write the fallback logic way more than just simple retry. Related discussions can be found at the link Retry with authenticators for adaptive authentication.
You could find samples how to do retry User's failed login attempts based adaptive authentication
. You can do much more than just retry following this way.
Related
I'm trying to implement user login with username and password on a spa using aws cognito, but I keep getting error on the auth flow.
Previously I was using 'amazon-cognito-identity-js' and it was all ok, but I'm moving to '#aws-sdk/client-cognito-identity-provider' and now I can't even login my user.
From web console I can see that Cognito app client enabled auth flows are
ALLOW_REFRESH_TOKEN_AUTH
ALLOW_CUSTOM_AUTH
ALLOW_USER_SRP_AUTH.
I tried almost every AuthFlowType value but browser console logs following error or ask for additional required params based on the auth flow tested.
Browser console log error
Uncaught (in promise) InvalidParameterException: Initiate Auth method not supported.
Login command code:
command = new AdminInitiateAuthCommand({
ClientId: AWS_COGNITO_APP_CLIENT_ID,
UserPoolId: AWS_COGNITO_USER_POOL_ID,
AuthFlow: AuthFlowType.<WHAT_VALUE_TO_INSERT_?>,
AuthParameters: {
USERNAME: username,
PASSWORD: password
}
});
Update#1
I added the ALLOW_USER_PASSWORD_AUTH flag to the allowed auth flows for the app client from the web console and used the AuthFlowType.USER_PASSWORD_AUTH value to login, but still I'm getting the same error.
An option that works for SPA is to use the Amplify Libraries, it has an Authentication API which abstracts the logic to call Cognito user pools to authenticate. You can configure the Amplify Authentication library as per this link:
https://docs.amplify.aws/lib/auth/start/q/platform/js/#re-use-existing-authentication-resource
After that you can sign in using the Auth.signIn method:
https://docs.amplify.aws/lib/auth/emailpassword/q/platform/js/#sign-in
I wrote my custom local authenticator. When I used it the lastLoginTime doesn't update. Logging with basic authenticator is ok.
Which extension responsible update lastLoginTime? What I need to do in my authenticator to update lastLoginTime? Thanks!
Update:
I made custom authenticator for using with user credentials that authenticator gets from XML Signature. The authenticator gets XML, verify signature, extract special_user_id and then checks this id in UserStroe in custom claim. If user with this claim value exists then authentificator gets user_name from User Store and finishes processAuthenticationResponse() with success.
In short
processAuthenticationResponse() {
...
String[] logins = userStoreManager.getUserList("http://wso2.org/claims/special_user_id", specialUserIdValue, "default");
context.setSubject(AuthenticatedUser.createLocalAuthenticatedUserFromSubjectIdentifier(logins[0]));
}
In IS-5.10.0, the last login time is updated only if the idle user suspension feature https://is.docs.wso2.com/en/5.10.0/learn/user-account-suspension/ is enabled.
IS-5.10.0 contains the identity-governance component version 1.4.1. Here is the code lines related to updating the last login time https://github.com/wso2-extensions/identity-governance/blob/57e510a61dc9042b55ffa0cbdceb13f508519f3a/components/org.wso2.carbon.identity.account.suspension.notification.task/src/main/java/org/wso2/carbon/identity/account/suspension/notification/task/handler/AccountSuspensionNotificationHandler.java#L84-L85
It's irrespective whether you use the basic authenticator / a custom authenticator. If you have enabled idle user account suspension feature,at every POST_AUTHENTICATION event this AccountSuspensionNotificationHandler's handleEvent should be invoked and update the last login time.
NOTE: In IS-5.11.0, the last login time value update logic is changed. It can be updated irrespective of idle user account suspension feature. Check https://github.com/wso2/product-is/issues/4515
Update:
Here is the reason for not triggering POST_AUTHENTICATION event when using the custom authenticator.
If you use the basic authenticator, user is authenticated from the IS userstore connecting through the userstore manager.
After the authentication happens in userstore https://github.com/wso2/carbon-kernel/blob/56d068221ab46e205d5b7188e2bc55134bfc08a9/core/org.wso2.carbon.user.core/src/main/java/org/wso2/carbon/user/core/common/AbstractUserStoreManager.java#L1757, the configured listeners' doPostAuthenticate method is invoked.
The POST_AUTHENTICATION event is triggered from IdentityMgtEventListener's , doPostAuthenticate method https://github.com/wso2-extensions/identity-governance/blob/57e510a61dc9042b55ffa0cbdceb13f508519f3a/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/listener/IdentityMgtEventListener.java#L122-L127
Since the above flow doesn't get executed when you use a custom authenticator which doesn't authenticate the user from WSO2 IS userstore, POST_AUTHENTICATION event is not triggered.
Possible options to follow to trigger POST_AUTHENTICATION event from the custom authenticator.
Override the public AuthenticatorFlowStatus process(HttpServletRequest request, HttpServletResponse response, AuthenticationContext context) throws AuthenticationFailedException, LogoutFailedException { method to user custom authenticator with same logic in the AbstractApplicationAuthenticator method. Then add
fireEvent(context, IdentityEventConstants.Event.POST_AUTHENTICATION, true);
before
return AuthenticatorFlowStatus.SUCCESS_COMPLETED;
similar to https://github.com/wso2/carbon-identity-framework/blob/527dba704487431b95c34461656cdb7496a0f0cc/components/authentication-framework/org.wso2.carbon.identity.application.authentication.framework/src/main/java/org/wso2/carbon/identity/application/authentication/framework/AbstractLocalApplicationAuthenticator.java#L80-L81
Extend your custom authenticator from AbstractLocalApplicationAuthenticator instead of AbstractApplicationAuthenticator. Note that there are differences in the authentication process method in those two classes.
I have a Vue.js webapp that I am trying to add simple authentication to using AWS Cognito and Amplify Auth. I have my user pool set up with "Authorization code grant" enabled for the OAuth flow. I also have the redirect URL set as https://example.auth.us-east-2.amazoncognito.com/login?response_type=code&client_id=XXXXXXXX&redirect_uri=https://example.com/auth/verify for the hosted UI.
This is what's within the page the hosted UI redirects to:
import { Auth } from "aws-amplify";
export default {
async created() {
try {
await Auth.currentSession();
} catch {
console.error("Not authorized");
}
}
}
When I sign in the first time through the hosted UI and am redirected, I get an error and am not recognized by Amplify as being authenticated. However if I sign in a second time, there is no error in the console and I have an authenticated session.
I do know that authorization code grant doesn't put the tokens in the URL, but I do see them in localstorage even on the first sign in. I have tried switching to using the "token" OAuth flow but the Amplify docs say the refresh token isn't provided that way and I'd like to not have sessions limited to 1 hour. Any guidance here?
For anyone facing the same problem, this seems to be a known issue.
The workaround is to subscribe to Hub actions and handle it there like
Hub.listen("auth", ({ payload: { event, data } }) => {
switch (event) {
case "signIn":
// signin actions
Auth.currentSession()
.then(user => console.log(user)) // redirect to default page
.error(err => console.log(err))
case "signOut":
// signout actions, redirect to '/' etc
case "customOAuthState":
// other changes
}
}
refer to https://github.com/aws-amplify/amplify-js/issues/5133#issuecomment-600759135
I have an app that uses Google auth with Firebase and React Native. Can I use the google authentication for user management and session creation with ConnectyCube?
The ConnectyCube docs describe Firebase account and project registration but don't explain how that relates to the ConnectyCube API.
Also in the ConnectyCube docs it give details the Create session with User authorization parameters and providers as Possible values: facebook, twitter, firebase_phone, but not google. Any help appreciated.
Since you have already set up an authentication system with Firebase, you probably do not need to use ConnectyCube authentication module to manage passwords and users.
At least in my case, we do not need that functionality but we still must login to ConnectyCube to use their services.
After the user logs in, we can subscribe to one's state and retrieve the user object:
async function onAuthStateChanged(user) {
// we do different operations here
await connectyCube.configure(user);
}
useEffect(() => {
const subscriber = auth().onAuthStateChanged(onAuthStateChanged);
return subscriber; // unsubscribe on unmount
}, []);
In ConnectyCube.js:
configure = async user => {
/*
Here you can:
Do session login
check for the active session
Format the user
Try Catch different scenarios
Sign up a user
Check if a user exists
*/
ConnectyCube.users
.signup(user)
.then(user => {
console.log('[ConnectyCube.users signup]', user);
})
.catch(error => {
console.log(`%c[ConnectyCube.users signup] ${error}`, 'color: red');
});
};
Hope it gives some ideas
Here's my workflow.
User presses a login button.
User is redirected to the API which redirects to a login page on a third party site (ADFS SAML).
User authenticates there, is returned to the API which decodes the response, creates a user and a JWT token (both stored in a datastore), and then redirects the user to Ember with a ?token= query parameter.
What I'd like to do is work this in to a custom ember-simple-auth authenticator (and authorizer?) in order to take advantage of the niceness of session and Authorization headers from there on.
Currently I've hacked an authenticator to do just the redirect to the identity provider. The rest of the API workflow is working. And I'm catching the token in a route on the way back and populating a User resource via a call to the database. But I feel that I'm heading down the wrong (and the long) path.
Any thoughts? Is this something that ember-simple-auth-token is designed for?
I solved this in last month. what i did was
click the login
redirect to the adfs
adfs login success-> redirect to my backend
backend generate a sso temp token with access token details which is
already there and only valid for 2 minutes.
backend redirect web with a GET with params of sso temp token
frontend take the params of sso temp token and make another post
ajax request to backend
Api will validate sso temp token and provide details ( access
token and refresh token ) to the user
read response data for the post request in 6 and update on ember
simple auth service using authenticate interface ( you can
customize this using custom authenticator )
here is the custom authenticator class
import Base from 'ember-simple-auth/authenticators/base';
import {isEmpty} from '#ember/utils';
export default Base.extend({
authenticate(data) {
return new Promise((resolve, reject) => {
if(data.access_token!=null){
resolve({
scope: data.scope,
access_token: data.access_token,
});
}else{
reject();
} })
},
restore(data) {
return new Promise((resolve, reject) => {
if (!isEmpty(data.access_token)) {
resolve(data);
} else {
reject();
}
});
},
});
i have created a route to handle in the frontend to get the token which is sent by backend. so the route takes sso token by a get param ( cause backend cannot do a post to emberapp) so when the route triggers i catch the param in route and do a post method again to validate the token.
we are using redis generated tokens. so since this question is asked about the emberjs i illustrated the answer to support you on frontend. i have illustrate the concept as well to show what you need to do. so its up to you to dig up and find more about it. like how to create temporary JWT token, how to validate it, how to redirect to you to your backend with claims from the adfs and etc. i think i provide answer to the initial question you asked which is
"How to implement an Ember Simple Auth using an external redirect"