The Task passes through the two strings from getuser() on to DBFirebase class. It then uses those strings to check if they exist in The Firebase Realtime Database. How can i return "CheckLogin" to Loginpage?. I tried changing the task to Task, but then it prevents the string from sending to the DB. Any Suggestions?
//LoginPage.xaml.cs
public async void getuser()
{
await services.LoginCheck(EmailEntry.Text, PasswordEntry.Text);
}
//DBFirebase.cs
public async Task LoginCheck(string email, string password)
{
var LoginCheck = (await Client.Child("users").OnceAsync<users>()).FirstOrDefault(a => a.Object.email == email && a.Object.password == password);
if (LoginCheck == null)
{
CheckLogin = false;
}
else
{
CheckLogin = true;
}
public async Task<bool> LoginCheck(string email, string password)
{
bool CheckLogin = false;
var LoginCheck = (await Client.Child("users").OnceAsync<users>()).FirstOrDefault(a => a.Object.email == email && a.Object.password == password);
if (LoginCheck == null)
{
CheckLogin = false;
}
else
{
CheckLogin = true;
}
return CheckLogin;
}
to call it
var check = await services.LoginCheck(EmailEntry.Text, PasswordEntry.Text);
As above I need create a function that returns "true" if a document exists, otherwise "false".
If the document doesn't exists then It need to be created before the function ends.
When I run it I have this exception :
Unhandled Exception: 'package:cloud_firestore/src/firestore.dart': Failed assertion: line 129 pos 12:
'isValidDocumentPath(documentPath)': a document path must point to a valid document.
Is pretty easy to understand that I'm not checking if the path exists before getting the collection but I don't know how to handle it.
This is the code:
Future<bool> checkMissingId(String id) async {
String str = id.toLowerCase();
String letter = str[0];
final snapShot =
await FirebaseFirestore.instance.collection(letter).doc(str).get();
if (snapShot == null || !snapShot.exists) {
//if not exists then create it
final _service = FirestoreService.instance;
_service.setData(
path: letter + str,
data: {'id': id},
);
return true;
} else // it already exists, return false
return false;
}
EDIT : new code but still doesn't work :
Future<bool> checkMissingId(String id) async {
String str = id.toLowerCase();
String letter = str[0];
String path = letter + "/" + str;
print(path);
try {
final snapShot =
await FirebaseFirestore.instance.collection(path).doc(str).get();
if (snapShot == null || !snapShot.exists) {
return true;
} else
return false;
} catch (e) {
print(e);
return false;
}
}
Future<bool> setId(String id) async {
String str = id.toLowerCase();
String letter = str[0];
String path = letter + "/" + str;
final _service = FirestoreService.instance;
try {
final snapShot =
await FirebaseFirestore.instance.collection(path).doc(str).get();
if (snapShot == null || !snapShot.exists) {
_service.setData(
path: path,
data: {'id': id},
);
return true;
} else
return false;
} catch (e) {
//print(e);
_service.setData(
path: path,
data: {'id': id},
);
return true;
}
}
Assuming id = "PaninoAvvelenato" :
I want to check if exists the document on path "p/paninoavvelenato", if not I need to create it.
Instead of using FirestoreService.
Future<bool> setId(String id) async {
String str = id.toLowerCase();
String letter = str[0];
try {
final snapShot = await FirebaseFirestore.instance.collection(letter).doc(str).get();
if (snapShot.exists) {
return false;
} else {
await FirebaseFirestore.instance.collection(letter).doc(str).set({'id': id});
return true;
}
} catch (e) {
// TODO: Do something clever.
return true;
}
}
It looks like document for path str is not exist and FirebaseFirestore.instance.collection(letter).doc(str).get(); throw exception
so better to place this code inside :
try {
// code that might throw an exception
FirebaseFirestore.instance.collection(letter).doc(str).get();
}
on Exception1 {
// code for handling exception
}
catch Exception2 {
// code for handling exception
}
I have this code where am supposed to upload an image and get the downloaded url but whenever i do that I get this error
my url is String url;. So please why is this not working as it is supposed to
PS
I checked other website to learn how to properly upload but it keeps giving me an error or is there a better way to do this.
My code image
uploadTask.whenComplete(()async{
url = await refs.getDownLoadURL();
....
});
Since it returns a Future you need to wait for it to be accessed
Example :
Future<String> createFolder(String folderName) async {
final dir = Directory(
'${(io.Platform.isAndroid ? await getExternalStorageDirectory() //FOR ANDROID
: await getApplicationSupportDirectory() //FOR IOS
)!.path}/$folderName');
var status = await Permission.storage.status;
if (!status.isGranted) {
await Permission.storage.request();
}
if ((await dir.exists())) {
return dir.path;
} else {
dir.create();
return dir.path;
}
}
Future<String> getIslamiSahittoBookFilePath(String savename) async {
Future<String> s = createFolder("Islami_Sahitto");
String filePath = await s;
Map<Permission, PermissionStatus> statuses = await [
Permission.storage,
//add more permission to request here.
].request();
io.File? f = null;
if (statuses[Permission.storage]!.isGranted) {
Directory? dir = await DownloadsPath.downloadsDirectory();
if (dir != null) {
String savePath = "${dir.path}/$filePath/$savename";
f = new io.File(savePath);
if (await f.exists()) {}
}
}
return f.toString();
}
Now this block You can use AnyWhere : Future String, to String :
bool isPreviousDownloaded = false;
String previousFilePath = "null";
getIslamiSahittoBookFilePath(fileNameToDownload).then((value) {
if (value != null) {
setState(() {
isPreviousDownloaded = true;
previousFilePath = value;
});
}
});
I am trying to make an ApI request with Digest Authentication. I found an answer to the above question FLUTTER How to implement Digest Authentification but it is not very clear. The docs for digest are very minimal.
Following is my code
import 'package:http/io_client.dart' as io_client;
import 'package:http/http.dart' as http;
try {
HttpClient authenticatingClient = HttpClient();
authenticatingClient.authenticate = (uri, scheme, realm) {
authenticatingClient.addCredentials(
uri,
realm,
HttpClientDigestCredentials(
DIGEST_AUTH_USERNAME, DIGEST_AUTH_PASSWORD));
return Future.value(true);
};
http.Client client = io_client.IOClient(authenticatingClient);
final response = await client.post(LOGIN_URL, body: {
"username": userName,
"password": password,
"user_group": 2
}).timeout(const Duration(seconds: 20));
if (response.statusCode == 200) {
debugPrint(response.body);
CurvesLoginModel curvesLoginModel = standardSerializers.deserializeWith(
CurvesLoginModel.serializer, json.decode(response.body));
return curvesLoginModel;
} else {
return null;
}
} on TimeoutException catch (_) {
return null;
} on SocketException catch (_) {
return null;
}
}
But what is realm in addCredentials.
Also is this the way to implement Digest Authentication in http for Flutter?
As soon as I hit my endpoint I get the following error Unhandled Exception: type 'int' is not a subtype of type 'String' in type cast
Realm is an arbitrary string provided by the web server to help you decide which username to use, in case you have more than one. It's sort of analogous to domain. In one domain your username might be fbloggs, in another fredb. By telling you the realm/domain you know which to provide.
Your cast problem is caused by using the value 2 in the body. That must be a Map<String, String>, but you have provided an integer. Replace it with 2.toString().
If somebody wants to know how to make digest auth with http then it is as follows
import 'dart:async';
import 'dart:convert';
import 'dart:math' as math;
import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart' as crypto;
import 'package:http/http.dart' as http;
class DigestAuthClient extends http.BaseClient {
DigestAuthClient(String username, String password, {inner})
: _auth = DigestAuth(username, password),
// ignore: prefer_if_null_operators
_inner = inner == null ? http.Client() : inner;
final http.Client _inner;
final DigestAuth _auth;
void _setAuthString(http.BaseRequest request) {
request.headers['Authorization'] =
_auth.getAuthString(request.method, request.url);
}
#override
Future<http.StreamedResponse> send(http.BaseRequest request) async {
final response = await _inner.send(request);
if (response.statusCode == 401) {
final newRequest = copyRequest(request);
final String authInfo = response.headers['www-authenticate'];
_auth.initFromAuthorizationHeader(authInfo);
_setAuthString(newRequest);
return _inner.send(newRequest);
}
// we should reach this point only with errors other than 401
return response;
}
}
Map<String, String> splitAuthenticateHeader(String header) {
if (header == null || !header.startsWith('Digest ')) {
return null;
}
String token = header.substring(7); // remove 'Digest '
var ret = <String, String>{};
final components = token.split(',').map((token) => token.trim());
for (final component in components) {
final kv = component.split('=');
ret[kv[0]] = kv.getRange(1, kv.length).join('=').replaceAll('"', '');
}
return ret;
}
String md5Hash(String data) {
var content = const Utf8Encoder().convert(data);
var md5 = crypto.md5;
var digest = md5.convert(content).toString();
return digest;
}
// from http_retry
/// Returns a copy of [original].
http.Request _copyNormalRequest(http.Request original) {
var request = http.Request(original.method, original.url)
..followRedirects = original.followRedirects
..persistentConnection = original.persistentConnection
..body = original.body;
request.headers.addAll(original.headers);
request.maxRedirects = original.maxRedirects;
return request;
}
http.BaseRequest copyRequest(http.BaseRequest original) {
if (original is http.Request) {
return _copyNormalRequest(original);
} else {
throw UnimplementedError(
'cannot handle yet requests of type ${original.runtimeType}');
}
}
// Digest auth
String _formatNonceCount(int nc) {
return nc.toRadixString(16).padLeft(8, '0');
}
String _computeHA1(String realm, String algorithm, String username,
String password, String nonce, String cnonce) {
String ha1;
if (algorithm == null || algorithm == 'MD5') {
final token1 = "$username:$realm:$password";
ha1 = md5Hash(token1);
} else if (algorithm == 'MD5-sess') {
final token1 = "$username:$realm:$password";
final md51 = md5Hash(token1);
final token2 = "$md51:$nonce:$cnonce";
ha1 = md5Hash(token2);
}
return ha1;
}
Map<String, String> computeResponse(
String method,
String path,
String body,
String algorithm,
String qop,
String opaque,
String realm,
String cnonce,
String nonce,
int nc,
String username,
String password) {
var ret = <String, String>{};
// ignore: non_constant_identifier_names
String HA1 = _computeHA1(realm, algorithm, username, password, nonce, cnonce);
// ignore: non_constant_identifier_names
String HA2;
if (qop == 'auth-int') {
final bodyHash = md5Hash(body);
final token2 = "$method:$path:$bodyHash";
HA2 = md5Hash(token2);
} else {
// qop in [null, auth]
final token2 = "$method:$path";
HA2 = md5Hash(token2);
}
final nonceCount = _formatNonceCount(nc);
ret['username'] = username;
ret['realm'] = realm;
ret['nonce'] = nonce;
ret['uri'] = path;
ret['qop'] = qop;
ret['nc'] = nonceCount;
ret['cnonce'] = cnonce;
if (opaque != null) {
ret['opaque'] = opaque;
}
ret['algorithm'] = algorithm;
if (qop == null) {
final token3 = "$HA1:$nonce:$HA2";
ret['response'] = md5Hash(token3);
} else if (qop == 'auth' || qop == 'auth-int') {
final token3 = "$HA1:$nonce:$nonceCount:$cnonce:$qop:$HA2";
ret['response'] = md5Hash(token3);
}
return ret;
}
class DigestAuth {
DigestAuth(this.username, this.password);
String username;
String password;
// must get from first response
String _algorithm;
String _qop;
String _realm;
String _nonce;
String _opaque;
int _nc = 0; // request counter
String _cnonce; // client-generated; should change for each request
String _computeNonce() {
math.Random rnd = math.Random();
List<int> values = List<int>.generate(16, (i) => rnd.nextInt(256));
return hex.encode(values);
}
String getAuthString(String method, Uri url) {
_cnonce = _computeNonce();
_nc += 1;
// if url has query parameters, append query to path
var path = url.hasQuery ? "${url.path}?${url.query}" : url.path;
// after the first request we have the nonce, so we can provide credentials
var authValues = computeResponse(method, path, '', _algorithm, _qop,
_opaque, _realm, _cnonce, _nonce, _nc, username, password);
final authValuesString = authValues.entries
.where((e) => e.value != null)
.map((e) => [e.key, '="', e.value, '"'].join(''))
.toList()
.join(', ');
final authString = 'Digest $authValuesString';
return authString;
}
void initFromAuthorizationHeader(String authInfo) {
Map<String, String> values = splitAuthenticateHeader(authInfo);
_algorithm = values['algorithm'];
_qop = values['qop'];
_realm = values['realm'];
_nonce = values['nonce'];
_opaque = values['opaque'];
}
bool isReady() {
return _nonce != null;
}
}
Then when calling your api
final response =
await DigestAuthClient(DIGEST_AUTH_USERNAME, DIGEST_AUTH_PASSWORD)
.post(LOGIN_URL, body: {
"USERNAME": userName,
"PASSWORD": password,
"USER_GROUP": "2"
}).timeout(const Duration(seconds: 20));
All credit goes to the following library https://pub.dev/packages/http_auth
I am trying to customize access token json object in my Web APi 2 project.
Which I have done successfully. But I am unable to figure out the case of failed request.
Here is my custom response:-
{ data: {}, success: 0, message: "failed" }
And following is a GrantResourceOwnerCredentials methon in ApplicationOAuthProvider which inherits OAuthAuthorizationServerProvider
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
ApplicationUserManager userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser user = userManager.Find(context.UserName, context.Password);
bool reqFailed = false;
string reqFailedMsg = "";
if (user == null)
{
reqFailed = true;
reqFailedMsg = "The user name or password is incorrect.";
}
if (!reqFailed && !user.EmailConfirmed)
{
reqFailed = true;
reqFailedMsg = "The user email is not confirmed.";
//context.SetError("invalid_grant", "The user email is not confirmed.");
//return;
}
if (!reqFailed && !user.IsActive)
{
reqFailed = true;
reqFailedMsg = "The user is disabled.";
//context.SetError("invalid_grant", "The user is disabled.");
//return;
}
if (reqFailed)
{
try
{
context.Response.Headers.Add(LMS.Utilities.Constants.MyMiddlewareHeader, new[] { (400).ToString() });
context.Response.Headers.Add(LMS.Utilities.Constants.MyMiddlewareHeaderMsg, new[] { reqFailedMsg });
}
catch (Exception ex)
{
}
return;
}
var form = await context.Request.ReadFormAsync();
if (form["deviceType"] != null && form["deviceToken"] != null)
{
user.DeviceToken = form["deviceToken"];
user.DeviceType = form["deviceType"];
userManager.Update(user);
}
ClaimsIdentity oAuthIdentity = userManager.GenerateUserIdentity(userManager, user,
OAuthDefaults.AuthenticationType);
ClaimsIdentity cookiesIdentity = userManager.GenerateUserIdentity(userManager, user,
CookieAuthenticationDefaults.AuthenticationType);
AuthenticationProperties properties = CreateProperties(user.UserName);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
//context.Request.Context.Authentication.SignIn(cookiesIdentity);
context.Request.Context.Authentication.SignIn(properties, cookiesIdentity);
//return Task.FromResult<object>(null);
}
And middleware class:-
public class AuthenticationMiddleware : OwinMiddleware
{
public AuthenticationMiddleware(OwinMiddleware next) : base(next) {
}
public override async Task Invoke(IOwinContext context)
{
await Next.Invoke(context);
if (context.Response.Headers.ContainsKey(Constants.MyMiddlewareHeader))
{
using (var reader = new StreamReader(context.Request.Body))
{
var headerValues = context.Response.Headers.GetValues(Constants.MyMiddlewareHeader);
context.Response.StatusCode = Convert.ToInt16(headerValues.FirstOrDefault());
context.Response.Headers.Remove(Constants.MyMiddlewareHeader);
var headerValuesMessage = context.Response.Headers.GetValues(Constants.MyMiddlewareHeaderMsg);
string msg = headerValuesMessage.FirstOrDefault().ToString();
context.Response.Headers.Remove(Constants.MyMiddlewareHeaderMsg);
string resp = Newtonsoft.Json.JsonConvert.SerializeObject(new ResponseViewModel<object>(new { }, (int)ResponseStatus.Fail, msg));
var response = context.Response;
var body = await reader.ReadToEndAsync();
var bytes = Encoding.UTF8.GetBytes(resp);
response.ContentLength = bytes.Length;
await response.WriteAsync(bytes);
return;
}
}
}
}
What I am getting in respose is:-
{"error":"invalid_grant"}{"Data":{},"Status":0,"Message":"The user name or
Which is invalid json as you can see.
Any help would be appreciated.
Thanks!