Failed assertion : 'email != null'? - database

does anyone know why my result is null? When I want to SignUp the debug console display : Failed assertion: line 183 pos 12: 'email != null': is not true. And it displays null. This is my SignUp code when I press SignUp Button and the other code ist my auth class. If anyone knows please comment.
Future <void> signUp() async {
if(_formKey.currentState.validate()){
setState(() {
isLoading = true;
});
await authService.signUpWithEmailAndPassword(_email,
_password).then((result) {
if(result != null){
Map<String,String> userDataMap = {
"Username" : _Username,
"Email" : _email,
"Nation" : _Nation,
};
databaseService.addUserInfo(userDataMap);
HelperFunction.saveUserLoggedInSharedPreference(true);
HelperFunction.saveUserNameSharedPreference(_Username);
HelperFunction.saveUserEmailSharedPreference(_email);
HelperFunction.saveUserNationSharedPreference(_Nation);
Navigator.pushReplacement(context, MaterialPageRoute(
builder: (context) => LoadingBarForUserCreation()
));
}else{
print(result);
}
}).catchError((e){
_showSettingPanelForEmail();
});
}
AuthService
class AuthService{
final FirebaseAuth _auth = FirebaseAuth.instance;
Userf _userFromFirebaseUser(User user){
return user != null ? Userf(uid: user.uid) : null;
}
Stream<Userf> get user {
return _auth.onAuthStateChanged
.map(_userFromFirebaseUser);
}
Future signInWithEmailAndPassword(String email, String password) async {
try {
User user = (await _auth.signInWithEmailAndPassword(
email: email, password: password)).user;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
Future signUpWithEmailAndPassword(String email, String password) async {
try {
User user = (await _auth.createUserWithEmailAndPassword(
email: email, password: password)).user;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
Future signOut() async {
try {
return await _auth.signOut();
} catch (e) {
print(e.toString());
return null;
}
}
}

Related

How a SPA with oidc-client could send token to external web api project

I am developing a SPA entirely in node.js/react that talks to an external identity server instance (we don't manage it) using the oidc-client module.
As for the client SPA itself, I was able to manage the login and logout phases.
This SPA, however, calls an external web api project (managed by us) developed in .net framework 4.8 to get the data
The people I am talking to wanted to register my SPA as a client in their identityserver and not the web api project.
I wanted to know if once I get the token on the client, I can manage a flow of permissions based on that token on my web api.
This is my authService and its configuration:
// configuration:
public static configDev: UserManagerSettings = {
authority: 'https://idservices.servicehosting.it/,
client_id: '<the client id of my spa>',
client_secret: '<the client secret of my spa>',
redirect_uri: 'https://localhost:9099/signin-callback',
silent_redirect_uri: 'https://localhost:9099/silent-renew',
response_type: 'code',
scope: 'openid profile email roles',
post_logout_redirect_uri: 'https://localhost:9099/signout-oidc',
loadUserInfo: true,
revokeAccessTokenOnSignout: true,
};
// service
import { UserManager, Log, User } from 'oidc-client';
import Constants from '../helpers/const/Constants';
export const AuthenticationResultStatus = {
Redirect: 'redirect',
Success: 'success',
Fail: 'fail',
};
export type UserState = {
redirectPath?: string;
};
export type AuthResponse = {
status: string;
message?: string;
userState?: UserState;
};
function buildError(message: string): AuthResponse {
return { status: AuthenticationResultStatus.Fail, message };
}
function buildSuccess(userState: UserState): AuthResponse {
return { status: AuthenticationResultStatus.Success, userState };
}
function buildRedirect(): AuthResponse {
return { status: AuthenticationResultStatus.Redirect };
}
type CallbackSub = {
callback: () => void;
subscription: number;
};
export class AuthService {
private userManager: UserManager;
private callbacks: CallbackSub[] = [];
private nextSubscriptionId = 0;
private currentUser: User = null;
public constructor() {
this.userManager = new UserManager(Constants.globalOidcConfig);
// Logger
Log.logger = console;
Log.level = Log.DEBUG;
this.userManager.events.addAccessTokenExpiring(() => {
console.log('token expiring');
void this.trySilentSignIn();
});
this.userManager.events.addAccessTokenExpired(() => {
console.log('token expired');
void this.userManager.removeUser().then(() => {
this.updateState(null);
});
});
this.userManager.events.addSilentRenewError((e) => {
console.log('silent renew error', e.message);
});
this.userManager.events.addUserLoaded((user) => {
console.log('user loaded', user);
});
this.userManager.events.addUserUnloaded(() => {
console.log('user unloaded');
});
this.userManager.events.addUserSignedIn(() => {
console.log('user logged in to the token server');
});
this.userManager.events.addUserSignedOut(() => {
console.log('user logged out of the token server');
});
}
updateState(user: User): void {
this.currentUser = user;
this.notifySubscribers();
}
subscribe(callback: () => Promise<void>): number {
this.callbacks.push({
// eslint-disable-next-line #typescript-eslint/no-misused-promises
callback,
subscription: this.nextSubscriptionId,
});
this.nextSubscriptionId += 1;
return this.nextSubscriptionId - 1;
}
unsubscribe(subscriptionId: number): void {
const subscriptionIndex = this.callbacks
.map((element, index) => (element.subscription === subscriptionId ? { found: true, index } : { found: false }))
.filter((element) => element.found === true);
if (subscriptionIndex.length !== 1) {
throw new Error(`Found an invalid number of subscriptions ${subscriptionIndex.length}`);
}
this.callbacks.splice(subscriptionIndex[0].index, 1);
}
notifySubscribers(): void {
for (let i = 0; i < this.callbacks.length; i++) {
const { callback } = this.callbacks[i];
callback();
}
}
async getUser(): Promise<User> {
if (this.currentUser?.profile == null) {
this.currentUser = await this.userManager.getUser();
}
return this.currentUser;
}
async getAccessToken(): Promise<string> {
const user = await this.userManager.getUser();
return user && user.access_token;
}
async trySilentSignIn(): Promise<User> {
await this.userManager
.signinSilent()
.then((user: User) => {
this.updateState(user);
return user;
})
.catch((error: Error) => {
void this.userManager.getUser().then((user: User) => {
console.log('silent renew error', error.message);
this.updateState(user);
return undefined;
});
});
return undefined;
}
// We try to authenticate the user in two different ways:
// 1) We try to see if we can authenticate the user silently. This happens
// when the user is already logged in on the IdP and is done using a hidden iframe
// on the client.
// 3) If the method above fails, we redirect the browser to the IdP to perform a traditional
// redirect flow.
async signin(userState: UserState): Promise<AuthResponse> {
try {
const silentUser = await this.userManager.signinSilent({ useReplaceToNavigate: true, state: userState });
this.updateState(silentUser);
return buildSuccess(silentUser.state as UserState);
} catch (silentError) {
// User might not be authenticated, fallback to redirect
console.log('Silent authentication error: ', silentError);
try {
await this.userManager.signinRedirect({ useReplaceToNavigate: true, state: userState });
return buildRedirect();
} catch (redirectError) {
console.log('Redirect authentication error: ', redirectError);
return buildError(redirectError as string);
}
}
}
async completeSignin(url?: string): Promise<AuthResponse> {
try {
const user = (await this.getUser()) || (await this.userManager.signinCallback(url));
const userState = user.state as UserState;
this.updateState(user);
return buildSuccess(userState);
} catch (error) {
console.log('There was an error signing in: ', error);
return buildError('There was an error signing in.');
}
}
// Redirect the browser to the IdP to perform a traditional
// post logout redirect flow.
async signout(): Promise<AuthResponse> {
try {
await this.userManager.signoutRedirect();
return buildRedirect();
} catch (redirectSignOutError) {
console.log('Redirect signout error: ', redirectSignOutError);
return buildError(redirectSignOutError as string);
}
}
async completeSignout(url?: string): Promise<AuthResponse> {
try {
await this.userManager.signoutCallback(url);
this.updateState(null);
return buildSuccess(null);
} catch (error) {
console.log('There was an error trying to log out ', error);
return buildError(error as string);
}
}
}
const authService = new AuthService();
export default authService;
As for the web api, for now I have only added this in my OWIN startup class:
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new List<string> { "openid", "profile", "email", "roles" },
TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateIssuerSigningKey = false,
ValidIssuer = "https://localhost:9099"
ValidAudience = "https://localhost:9099", // <- I think this is wrong
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(ConfigurationManager.AppSettings["JwtKey"]))
}
});
and this in WebApiConfig to add the bearer token authentication filter instead of its default one:
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
how could i set my webapi to correctly receive the token from my client (the spa)? thank you!
`

How to use roles?

login = async (creds: UserFormValues) => {
try {
const user = await agent.Account.login(creds);
store.commonStore.setToken(user.token);
runInAction(() => this.user = user);
history.push('/activities');
store.modalStore.closeModal();
} catch (error) {
throw error;
}
}
I have this "login" that I want to edit it to make it with roles. Like:
login = async (creds: UserFormValues) => {
try {
const user = await agent.Account.login(creds);
store.commonStore.setToken(user.token);
runInAction(() => this.user = user);
if(user.role = "admin"){
history.push('/activities');
}
else{
history.push('/home');
}
store.modalStore.closeModal();
} catch (error) {
throw error;
}
}
But I get the warning "Expected a conditional expression and instead saw an assignment no-cond-assign" and still the platform runs but it ignores the if statement. How can I make a conditional expression about this(If you can also show me the code about it)? Also I have 5 roles which should go all on different pages.
login = async (creds: UserFormValues) => {
try {
const user = await agent.Account.login(creds);
store.commonStore.setToken(user.token);
runInAction(() => this.user = user);
if(user.role === "admin"){
history.push('/activities');
}
else{
history.push('/home');
}
store.modalStore.closeModal();
} catch (error) {
throw error;
}
}
This is the updated code, when I login as admin it redirects me to home and not into activities, like the if doesn't exist.

I have a problem with my function authentication. I get an empty token while everything works fine when I use postman

I have a problem with authentication using reactJs in frontend and spring boot and jwt in backend. when I use postman I get the token but when I implement it in reactJs I get an empty token and the following error message
enter image description here
enter image description here
enter image description here
this is my log in function :
onLogin = (e) => {
e.preventDefault();
const user = {username: this.state.username, password: this.state.password};
courseService.login(user)
.then(response => {
console.log(response);
const jwtToken = response.headers.get("token");
if (jwtToken !== undefined) {
localStorage.setItem("token", jwtToken);
this.setState({isAuthenticated: true});
this.props.history.push('/');
}
else {
this.setState({open: true});
}
})
.catch(err => console.error(err))
}
this is courseService :
class CourseService {
retrieveAllCourses() {
return axios.get(COURSE_API_URL+'/courses');
};
getCoursesByThemeId = (id) => {
return axios.get(COURSE_API_URL+'/themes/'+id+'/courses');
}
getCourse = (id) => {
return axios.get(COURSE_API_URL+'/courses/'+id);
}
getTheme = (id) => {
return axios.get(COURSE_API_URL+'/themes/'+id);
}
findInscriptionByCourseId = (courseId)=>{
return axios.get(INSCRIPTION_API_URL+'/inscription/'+courseId)
}
retrieveAllThemes() {
return axios.get(COURSE_API_URL+'/themes');
};
editCourse(course) {
return axios.put(COURSE_API_URL + '/courses/' + course.id, course);
};
addCourse(course) {
return axios.post(COURSE_API_URL+'/new-course', course);
};
addUser(user){
return axios.post(USER_API_URL+'/register', user);
}
login(user) {
return axios.post(USER_API_URL+'/login', user);
};
deleteCourse = (id) => {
return axios.delete(COURSE_API_URL+'/courses/'+id);
};
addInscription(inscription){
return axios.post(INSCRIPTION_API_URL+'/inscriptions',inscription);
};
}
export default new CourseService();

My Request by token query is returning null

After the token has been stored in the Local Storage, I have a function where I can load the data of the currentStudent when the token is verified but the function is returning null.
this is my resolvers code
getCurrentStudent: async (
root,
{ studentId },
{ currentStudent, Student }
) => {
if (!currentStudent) {
return null;
}
const student = await Student.findOne({
studentId: currentStudent.studentId
});
return student;
}
and then i tried to make a context with the ApolloServer instance
const server = new ApolloServer({
typeDefs,
resolvers,
context: async ({ req }) => {
const token = req.headers["authorization"];
if (token !== null) {
try {
const currentStudent = await jwt.verify(token, process.env.SECRET);
req.currentStudent = currentStudent;
} catch (err) {
console.log(err);
}
}
}
});
this should verify my token and return the currentUser.
The function you pass to context should return a context object, or a Promise that will resolve to one:
context: async ({ req }) => {
const token = req.headers["authorization"];
let currentStudent;
if (token !== null) {
try {
const currentStudent = await jwt.verify(token, process.env.SECRET);
currentStudent = currentStudent;
} catch (err) {
console.log(err);
}
}
return {
currentStudent,
};
}
You can then utilize that context inside any of your resolvers, for example:
const resolvers = {
Query: {
currentStudent: (root, args, context) => {
return context.currentStudent;
}
}
};

AWS Cognito completeNewPasswordChallenge calls onFailure method but the user is confirmed in AWS Console

I'm using AWS Cognito Javascript SDK in a react application. I have a user that was created in the AWS Console by an admin, and when the user is logged in for the first time they have to reset their password. I go through the newPasswordRequired flow, and when I call the completeNewPasswordChallenge function with the parameters, the onFailure callback is ran. When I log the error I get, {code: "UnknownError", message: "Unknown error"}. However, when I check the AWS Console, the user in the user pool is changed from FORCE_CHANGE_PASSWORD to CONFIRMED.
My code is:
class LoginScreenContainer extends Component {
constructor(props) {
super(props);
this.state = {
isInvalidForm: null,
isFirstLogin: false,
user: null,
userAttr: null
}
this.onFormSubmission = this.onFormSubmission.bind(this);
this.updatePassword = this.updatePassword.bind(this);
}
onFormSubmission = (username, password) => {
const poolData = {
UserPoolId : AWSConfig.cognito.USER_POOL_ID,
ClientId : AWSConfig.cognito.APP_CLIENT_ID
}
const userPool = new CognitoUserPool(poolData);
const userData = {
Username: username,
Pool: userPool
}
const cognitoUser = new CognitoUser(userData);
const authenticationData = {
Username : username,
Password : password
}
const authenticationDetails = new AuthenticationDetails(authenticationData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: (result) => {
console.log(result);
},
onFailure: (err) => {
console.log("Authenticate user failure");
console.log(err);
this.setState({ isInvalidForm: true });
},
newPasswordRequired: (userAttributes) => {
delete userAttributes.email_verified;
delete userAttributes.phone_number_verified;
userAttributes.name = authenticationDetails.username;
console.log(userAttributes);
this.setState({
isFirstLogin: true,
user: cognitoUser,
userAttr: userAttributes
});
}
});
}
updatePassword = (newPassword) => {
const cognitoUser = this.state.user;
const userAttr = this.state.userAttr;
cognitoUser.completeNewPasswordChallenge(newPassword, userAttr, {
onSuccess: (result) => {
console.log("NEW PASSWORD COMPLETED: ");
console.log(result);
},
onFailure: (err) => {
console.log(err);
}
});
}
render() {
return (
<div>
{this.state.isFirstLogin ? (
<NewPasswordForm updatePassword={this.updatePassword} />
) : (
<LoginScreenComponent isInvalidForm={this.state.isInvalidForm} onFormSubmission={this.onFormSubmission}/>
)}
</div>
);
}
}
I believe you need to call completeNewPasswordChallenge within the newPasswordRequired callback.
newPasswordRequired: (userAttributes, requiredAttributes) => {
delete userAttributes.email_verified
cognitoUser.completeNewPasswordChallenge(newPw, userAttributes, {
onSuccess: result => {
AWS.config.credentials.refresh(err => {
if (err) {
throw err
} else {
// do something
}
})
},
newPasswordRequired: (userAttributes, requiredAttributes) => {
delete userAttributes.email_verified
// phone number as well
cognitoUser.completeNewPasswordChallenge(newPw, userAttributes, this.newPasswordRequired)
},
onFailure: err => {
throw err
}
})
},
I believe you have MFA on your account and you need to handle it from callback:
mfaSetup: (challengeName, challengeParameters) => { ... }
When you're handling mfaSetup form cognitoUser.authenticateUser() callback all is good if it's required, but from completeNewPasswordChallenge() callback there is no mfaSetup() in typings, which I believe AWS colleagues should fix it ASAP.
That's why you have empty error code, please check response tab in network dev tools on post req you made. I believe you'll find there MFA_SETUP challenge to solve.

Resources