I am currently working on a flutter application using dart language. I am trying to use AstraDB for my login page authentication of users’ email and password using the http flutter package.
The following are the code I used for creating the the data in AstraDB as well as for the application, for the api urls I have followed the same format as indicated with my respective values and "users" is the name of my table in AstraDB.
CQL command used to create the table in AstraDB Console:
CREATE TABLE IF NOT EXISTS users (
email text PRIMARY KEY,
password text
);
CQL command used to insert data in AstraDB Console:
INSERT INTO users (email, password) VALUES ('[email protected]', 'password123');
Dart code for the application’s login page in Android Studio:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'AstraDB HTTP Demo',
home: LoginPage(),
);
}
}
class LoginPage extends StatefulWidget {
@override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
Future<void> _login() async {
final response = await http.post(
Uri.parse('https://YOUR-ASTRA-DB-ID-YOUR-ASTRA-DB-REGION.apps.astra.datastax.com/api/rest/v2/keyspaces/keyspace_name/users?apiToken=YOUR-APPLICATION-TOKEN'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
'email': _emailController.text,
'password': _passwordController.text,
}),
);
if (response.statusCode == 200) {
print('Login Successful');
// TODO: Handle successful login.
} else {
throw Exception('Failed to log in.');
}
}
Future<void> _signup() async {
final response = await http.post(
Uri.parse('https://YOUR-ASTRA-DB-ID-YOUR-ASTRA-DB-REGION.apps.astra.datastax.com/api/rest/v1/signup'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
'email': _emailController.text,
'password': _passwordController.text,
}),
);
if (response.statusCode == 200) {
print('Signup Successful');
// TODO: Handle successful signup.
} else {
throw Exception('Failed to sign up.');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('AstraDB HTTP Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
width: 300,
child: TextField(
controller: _emailController,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Email',
),
),
),
SizedBox(height: 30),
SizedBox(
width: 300,
child: TextField(
controller: _passwordController,
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
),
),
),
SizedBox(height: 30),
ElevatedButton(
onPressed: _login,
child: Text('Login'),
),
SizedBox(height: 15),
ElevatedButton(
onPressed: _signup,
child: Text('Sign Up'),
),
],
),
),
);
}
}
Firstly, when trying running the application on my tablet and typing in the respective values in the login fields, it provides me with the following message in Android Studios’ terminal.
E/flutter (28320): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Exception: Failed to log in.
E/flutter (28320): #0 _LoginPageState._login (package:sign_in/main.dart:42:7)
E/flutter (28320): <asynchronous suspension>
Secondly, I tried checking if the ApiURL was correct using my web browser (Google Chrome) and it provided this error on the page. I am not sure if this is the correct way to check.
{"description":"where parameter is required","code":400}
I expected the application’s login to be successful upon filling in the appropriate details, allowing the user to proceed to use the rest of the application features. I initially wanted to add a sign up feature as well but my login itself does not work itself. However, this was not the case and I have been trying to find a solution for this for approximately two weeks now. All help is appreciated. Thank you.
2
Answers
You want to access the data in table
users
. There a couple of things to update.Table Design
To authenticate user we want to execute the query
select email,password from users
as such both email and password should be part of the key. The table should be changed to:In the table make sure you do not store the password in clear text but rather encode it in SHA1 for security reason.
The Query
To use HTTP API, You will need an authentication key to be passed in the header. (this is the cause of your error above). To create one follow the instructions
If you look at the Swagger UI available in Astra UI your are targeting this resource
The output look like:
I propose you to use the field to tell if authentication is successful or not.
You need to pass the authentication token in the header section. In your app, you have incorrectly included the token in the URI which is incorrect.
To illustrate, here are the contents of my
users
table:WARNING: I stored the password in plain text for simplicity but this is not recommended. Best practice is to hash-encode the password before saving it.
The API endpoint I use to query is (note the
@
symbol in the email address is HTTP-encoded):The headers are:
This will return the following response: