An application was written using the WTelegramClient library. There was a task to use the proxy server settings to connect to the Internet:
Address,
Port,
Username,
Password.
Now the connection is made without a proxy.
We declare variables:
using TL;
private WTelegram.Client _client;
private User _user;
private TelegramSettings telegramSettings = null;
We fill it with values:
private void saveSettingButton_Click(object sender, EventArgs e)
{
if (telegramSettings == null) telegramSettings = new TelegramSettings();
telegramSettings.UseProxy = checkEditUseProxy.Checked;
telegramSettings.ProxyHost = textEditProxyHost.Text.Trim();
telegramSettings.ProxyPort = textEditProxyPort.Text.Trim() == "" ? 0 : Convert.ToInt32(textEditProxyPort.Text.Trim());
telegramSettings.ProxyUserName = textEditProxyUserName.Text.Trim();
telegramSettings.ProxyPassword = textEditProxyPassword.Text.Trim();
telegramSettings.PhoneNumber = (string)textBoxPhone.EditValue;
telegramSettings.API_Hash = textBoxApiHash.Text.Trim();
telegramSettings.API_ID = textBoxApiID.Text.Trim();
}
Making changes to the Сonfig:
string Config(string what)
{
switch (what)
{
case "api_id": return telegramSettings.API_ID;
case "api_hash": return telegramSettings.API_Hash;
case "phone_number": return telegramSettings.PhoneNumber;
case "verification_code":
case "password": // if user has enabled 2FA
BeginInvoke(new Action(() => CodeNeeded(what.Replace('_', ' '))));
_codeReady.Reset();
_codeReady.Wait();
return textBoxCode.Text;
case "first_name":
case "last_name":
return null; // if sign-up is required
default: return null;
};
}
Connecting
_client = new WTelegram.Client(Config);
_user = await _client.LoginUserIfNeeded();
How to apply proxy settings?
Using a proxy with WTelegramClient is described in the Examples documentation:
Set TcpHandler before login:
client.TcpHandler = async (address, port) =>
{
var proxy = new Socks5ProxyClient(ProxyHost, ProxyPort, ProxyUsername, ProxyPassword);
return proxy.CreateConnection(address, port);
};
Related
I am trying to implement on a Blazor-Server side application a simple login against LDAP server and use cookie to store user claims. I have the MainLayout set to Authorized, if the user is not authenticated it will be re-direct to Login page. I have already tested the LDAP connection and it works properly, the problem is no matter what I do the cookie doesn't get created in the browser. When I run the POST command I see the HttpStatusCode.OK but the cookie it's not created and the browser re-direct again to login page of course.
Can someone please tell me what am I doing wrong? My code:
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddControllersWithViews().AddRazorRuntimeCompilation();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
AuthenticationController.cs
[ApiController]
public class AuthenticationController : Controller
{
[HttpPost]
[Route("authentication/login")]
public async Task<ActionResult> Login([FromBody]UserCredentials credentials)
{
string path = "LDAP://serveraddress.xxx";
try
{
using DirectoryEntry entry = new(path, credentials.Username, credentials.Password);
using DirectorySearcher searcher = new(entry);
searcher.Filter = $"(&(objectclass=user)(objectcategory=person)(samaccountname={credentials.Username}))";
var result = searcher.FindOne();
if (result != null)
{
List<Claim> claims = new();
claims.Add(new Claim(ClaimTypes.Name, credentials.Username));
//Get Groups
ResultPropertyCollection fields = result.Properties;
foreach (var group in result.Properties["memberof"])
{
var distinguishedName = new X500DistinguishedName(group.ToString());
var commonNameData = new AsnEncodedData("CN", distinguishedName.RawData);
var commonName = commonNameData.Format(false);
if (!string.IsNullOrEmpty(commonName))
{
claims.Add(new Claim(ClaimTypes.Role, commonName));
}
}
//Get Emails
foreach (var email in result.Properties["mail"])
{
claims.Add(new Claim(ClaimTypes.Email, email.ToString()));
}
ClaimsIdentity claimsIdentity = new(claims, CookieAuthenticationDefaults.AuthenticationScheme);
AuthenticationProperties authProperties = new()
{
AllowRefresh = true,
IssuedUtc = DateTime.Now,
ExpiresUtc = DateTimeOffset.Now.AddDays(1),
IsPersistent = true,
};
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties);
return Ok();
}
else
{
return NotFound("User Not Found!");
}
}
catch (Exception)
{
return NotFound("Login credentials is incorrect!");
}
}
[HttpPost]
[Route("authentication/logout")]
public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return Ok();
}
}
Login.razor
#page "/login"
#page "/login/{ErrorMessage}"
#layout CenteredBlockLayout
#attribute [AllowAnonymous]
<MudPaper Elevation="25" Class="pa-8" Width="100%" MaxWidth="500px">
<MudItem><img src="/images/logo.svg" alt="Logo" style="width:400px; height:50px;" /></MudItem>
<MudText Typo="Typo.h4" GutterBottom="true">Sign In</MudText>
<MudTextField #bind-Value="#Username" T="string" Label="Username"/>
<MudTextField #bind-Value="#Password" T="string" Label="Password"/>
<MudButton OnClick="(() => PerformLoginAsync())">Sign In</MudButton>
</MudPaper>
#if (!string.IsNullOrEmpty(ErrorMessage))
{
<MudAlert Severity="Severity.Error">#ErrorMessage</MudAlert>
}
Login.razor.cs
public partial class Login
{
public string Username { get; set; }
public string Password { get; set; }
[Parameter]
public string ErrorMessage { get; set; }
[Inject]
HttpClient Client { get; set; }
[Inject]
private NavigationManager NavMan { get; set; }
private async Task PerformLoginAsync()
{
if (!string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password))
{
UserCredentials cred = new UserCredentials
{
Username = Username,
Password = Password
};
var serialized = JsonConvert.SerializeObject(cred);
var stringContent = new StringContent(serialized, Encoding.UTF8, "application/json");
using var result = await Client.PostAsync($"NavMan.BaseUri}authentication/login", stringContent);
if (result.StatusCode == System.Net.HttpStatusCode.OK)
{
NavMan.NavigateTo("/", true);
}
else
{
ErrorMessage = await result.Content.ReadAsStringAsync();
}
}
}
}
I believe you need to append the cookie to the response. I haven't tested this with your code but it should work something like this:
HttpContext.Response.Cookies.Append("my_cookie", claimsString, new CookieOptions()
{
Domain = "mydomain.com",
SameSite = SameSiteMode.Lax,
Secure = true,
Path = "/",
Expires = DateTime.UtcNow.AddDays(1)
}
(These cookie options are just an example, of course. Tailor them to your specific needs.)
Keep in mind that you'll need to convert your claims to a string so that you can store it as the value in a cookie. In our case we store claims in a JWT, so that's what gets stored in the cookie. Here's how I do it:
public string CreateJWT(HttpContext httpContext, User user)
{
var handler = new JwtSecurityTokenHandler();
var descriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[] {
new Claim(ClaimTypes.GivenName, user.FirstName),
new Claim(ClaimTypes.Surname, user.LastName),
new Claim(ClaimTypes.Name, $"{user.FirstName} {user.LastName}"),
new Claim(ClaimTypes.Email, user.Email),
}),
Expires = DateTime.UtcNow.AddMinutes(Config.AccessExpMins),
Issuer = Config.Issuer,
Audience = Config.Audience,
SigningCredentials = new SigningCredentials(Key, SecurityAlgorithms.RsaSha256)
};
var token = handler.CreateJwtSecurityToken(descriptor);
var accessToken = handler.WriteToken(token);
httpContext.Response.Cookies.Append("my_cookie", accessToken, new CookieOptions()
{
Domain = Config.CookieDomain,
SameSite = SameSiteMode.Lax,
Secure = true,
Path = "/",
Expires = DateTime.UtcNow.AddMinutes(Config.AccessExpMins)
});
return accessToken;
}
As for parsing the JWT, I'm sure there are a number of ways to go about it. The one that worked for me was this one.
I am working on a project with IdentityServer4, Asp.Net.Identity and all is done in MVC and Razor. I have most of it working, the only thing I am struggling with is the RememberMe capability. Currently Idsrv sets the cookie even though RememberMe is false when logging in.
Here is my code:
The LoginModel challenges Idsrv with the oidc Authentication Scheme.
public class LoginModel : PageModel {
public IActionResult OnGet() {
return Challenge(new AuthenticationProperties {
RedirectUri = "/" }, "oidc");
}
}
}
Here is my startup extension method for the client authentication
public static void AddClientAuthentication(this IServiceCollection services) {
services.AddAuthentication(options => {
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options => {
options.SignInScheme = "Cookies";
options.Authority = AuthorityUrl;
options.RequireHttpsMetadata = true;
options.ResponseType = "code id_token";
options.SaveTokens = true;
options.ClientId = "*ClientId*";
options.ClientSecret = "*ClientSecret*";
options.Scope.Add("profile");
options.Scope.Add("openid");
});
}
And here is my login-logic:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model) {
if (!ModelState.IsValid) {
return View(model);
}
SignInResult result = await signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberLogin, true);
if (result.Succeeded) {
ApplicationUser user = await userManager.FindByEmailAsync(model.Email);
await events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.UserName));
return Redirect("https://localhost:5002/home");
}
The issue is, that cookies are set even though model.RememberLogin is false. Does anyone have a solution for that? Thank you in advance!
So, it was not a bug in my code. I didn't know that there is a cookie set for the duration of the browser session.
We have an application that is hosted on multiple domains. Currently we have to deploy to different places with configuration defining the cookie domain. Is there a way to do this all within one application?
The following code is what we're doing within Startup, ConfigureServices
var cookieDomain = Configuration["CookieDomain"];
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = "/Account/LogIn";
options.Cookie.Name = ".SharedCookie";
options.Cookie.Domain = cookieDomain;
options.Cookie.Path = "/";
options.Cookie.HttpOnly = false;
options.Cookie.SameSite = SameSiteMode.None;
});
"mydomain.com" works fine.
"mydomain.com,myotherdomain.com" doesn't work at all (no errors, just returns a cookie with the domain "mydomain.com,myotherdomain.com"
calling ConfigureApplicationCookie twice results in the last taking precedence
I achieved this by implementing a CookieManager and setting the cookie domain for each request, so it is possible to use the same code deployed to the same place, but using different domains.
var cookieDomain = Configuration["CookieDomain"];
services.ConfigureApplicationCookie(options =>
{
options.CookieManager = new CookieManager();
options.LoginPath = "/Account/LogIn";
options.Cookie.Name = cookieDomain;
options.Cookie.Domain = cookieDomain;
options.Cookie.Path = "/";
options.Cookie.HttpOnly = false;
options.Cookie.SameSite = SameSiteMode.None;
});
public class CookieManager : Microsoft.AspNetCore.Authentication.Cookies.ICookieManager
{
private readonly Microsoft.AspNetCore.Authentication.Cookies.ICookieManager ConcreteManager;
public CookieManager()
{
ConcreteManager = new Microsoft.AspNetCore.Authentication.Cookies.ChunkingCookieManager();
}
public string GetRequestCookie(HttpContext context, string key)
{
return ConcreteManager.GetRequestCookie(context, key);
}
public void AppendResponseCookie(HttpContext context, string key, string value, CookieOptions options)
{
options.Domain = context.Request.Host.Value;
ConcreteManager.AppendResponseCookie(context, key, value, options);
}
public void DeleteCookie(HttpContext context, string key, CookieOptions options)
{
options.Domain = context.Request.Host.Value;
ConcreteManager.DeleteCookie(context, key, options);
}
}
I use following code for Facebook login and access user information like albums and pictures. I have set code to get access token using following code. Now, the problem is I need to get access token everytime when user open application. However, once user authenticate, application will not ask for authenticate until user close the application. But it will ask for authenticate again after user reopen application. This way user will frustrate if they will ask to authentication everytime they will try to access albums or any other things of facebook.
Is there anyway to skip this? I mean once user provided access of Facebook, application must not ask for login(authenticate). I will have access token but I don't know how to use to play with authentication. So, we can avoid authentication frequently.
My Code:
public class FacebookService : IFacebookService
{
private readonly string[] permissions = { "public_profile", "email", "user_birthday", "user_photos" };
public event EventHandler<FacebookUser> LoginCompleted;
public string Token => AccessToken.CurrentAccessToken.TokenString;
public void Logout()
{
LoginManager manager = new LoginManager();
manager.LogOut();
}
public void LogInToFacebook()
{
if (AccessToken.CurrentAccessToken == null)
{
ObtainNewToken(LogInToFacebook);
return;
}
var fields = new[] { "name", "email", "birthday", "gender", "picture" };
var query = $"/me?fields={string.Join(",", fields)}";
var token = AccessToken.CurrentAccessToken.TokenString;
var request = new GraphRequest(query, null, token, null, "GET");
request.Start((connection, result, error) =>
{
if (error != null)
{
HandleError(error.LocalizedDescription);
}
else
{
var userInfo = result as NSDictionary;
var id = userInfo["id"].ToString();
var email = userInfo["email"].ToString();
var name = userInfo["name"].ToString();
var birthday = userInfo["birthday"].ToString();
var gender = userInfo["gender"].ToString();
var picture = ((userInfo["picture"] as NSDictionary)["data"] as NSDictionary)["url"].ToString();
var args = new FacebookUser(id, email, name, birthday, gender, picture);
LoginCompleted?.Invoke(this, args);
}
});
}
public async System.Threading.Tasks.Task RequestAlbums(Action<FacebookAlbum[]> callback)
{
if (AccessToken.CurrentAccessToken == null)
{
ObtainNewTokenForAlbum(callback);
return;
}
using (HttpClient client = new HttpClient())
{
try
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
var host = "https://graph.facebook.com/";
var json = await client.GetStringAsync($"{host}me/albums");
var data = JObject.Parse(json).First.First.ToString();
var albums = JsonConvert.DeserializeObject<FacebookAlbum[]>(data);
var getPhotosTasks = new List<System.Threading.Tasks.Task>();
foreach (var album in albums)
getPhotosTasks.Add(System.Threading.Tasks.Task.Run(() => RequestPhotos(album)));
await System.Threading.Tasks.Task.WhenAll(getPhotosTasks.ToArray());
callback(albums);
}
catch (Exception ex1)
{
HandleError(ex1.Message);
}
}
}
private void ObtainNewTokenForAlbum(Action<FacebookAlbum[]> callback)
{
var login = new LoginManager();
login.LogInWithReadPermissions(permissions, null, (r, e) =>
{
if (e == null && !r.IsCancelled)
{
RequestAlbums(callback);
}
else
HandleError(e?.LocalizedDescription);
});
}
private async System.Threading.Tasks.Task RequestPhotos(FacebookAlbum album)
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
try
{
var host = "https://graph.facebook.com/";
var json = await client.GetStringAsync($"{host}{album.Id}/photos?fields=source,picture");
var data = JObject.Parse(json)["data"].ToString();
album.Photos = JsonConvert.DeserializeObject<FacebookPicture[]>(data);
}
catch (Exception exc)
{
HandleError(exc.Message);
}
}
}
private void ObtainNewToken(Action callback)
{
var login = new LoginManager();
login.LogInWithReadPermissions(permissions, null, (r, e) =>
{
if (e == null && !r.IsCancelled)
callback?.Invoke();
else
HandleError(e?.LocalizedDescription);
});
}
private void HandleError(string messageDescription)
{
messageDescription = messageDescription ?? "Request was cancelled";
_notificationService.DisplayNotification(messageDescription, Colors.d8Red);
}
}
AppDelegate
public override bool FinishedLaunching(UIApplication uiApplication, NSDictionary launchOptions)
{
UAirship.TakeOff();
RegisterServices();
SetupFacebookSDK();
FFImageLoading.Forms.Touch.CachedImageRenderer.Init();
var dummy = new FFImageLoading.Forms.Touch.CachedImageRenderer();
Xamarin.Forms.Forms.Init();
LoadApplication(new App());
UIApplication.SharedApplication.StatusBarHidden = false;
UIApplication.SharedApplication.SetStatusBarStyle(UIStatusBarStyle.LightContent, false);
_networkManager = new NetworkManager();
OverrideDefaultListViewCustomActionsColors();
UAirship.Push.UserPushNotificationsEnabled = true;
new PhotoAccessChecker();
return ApplicationDelegate.SharedInstance.FinishedLaunching(uiApplication, launchOptions);
}
void SetupFacebookSDK()
{
FacebookProfile.EnableUpdatesOnAccessTokenChange(true);
FacebookSettings.AppID = "000000000049000";
FacebookSettings.DisplayName = "MyProduct";
}
public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
{
return ApplicationDelegate.SharedInstance.OpenUrl(application, url, sourceApplication, annotation);
}
I guess you forgot initialize FBSDK in AppDelegate.
Check your code if return ApplicationDelegate.SharedInstance.FinishedLaunching (application, launchOptions); has been executed in FinishedLaunching.
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
Settings.AppID = appId;
Settings.DisplayName = appName;
// ...
// This method verifies if you have been logged into the app before, and keep you logged in after you reopen or kill your app.
return ApplicationDelegate.SharedInstance.FinishedLaunching (application, launchOptions);
}
public override bool OpenUrl (UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
{
// We need to handle URLs by passing them to their own OpenUrl in order to make the SSO authentication works.
return ApplicationDelegate.SharedInstance.OpenUrl (application, url, sourceApplication, annotation);
}
My OWIN Web.API 2 Hosted on EC2 will not authorize a JWT token. I have tested the functionality locally with out a problem but once I publish it out to my docker container hosted on EC2 it responds with a 401. I am using the default RS256 Algorithm and these settings:
var domain = Environment.GetEnvironmentVariable("AUTH0_DOMAIN");
var audience = Environment.GetEnvironmentVariable("AUTH0_CLIENT_IDS");
var keyResolver = new OpenIdConnectSigningKeyResolver(domain);
appBuilder.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] { audience },
TokenValidationParameters = new TokenValidationParameters()
{
ValidAudience = audience,
ValidIssuer = domain,
IssuerSigningKeyResolver = (token, securityToken, identifier, parameters) => keyResolver.GetSigningKey(identifier)
}
});
My Endpoint simply states whether your are authenticated or not.
[Authorize]
[Route("secure")]
public HttpResponseMessage GetSecured()
{
var userId = ClaimsPrincipal.Current.Identity.GetUserId();
return Request.CreateResponse($"Hello, {userId}! You are currently authenticated.");
}
Here is my Startup config:
public void Configuration(IAppBuilder appBuilder)
{
appBuilder.UseCors(CorsOptions.AllowAll); //must be first
Auth0Config.Register(appBuilder);
var httpConfiguration = new HttpConfiguration();
httpConfiguration.MapHttpAttributeRoutes();
UnityConfig.Register(httpConfiguration);
appBuilder.UseWebApi(httpConfiguration);
}
I no longer use the OWIN pipeline but from a previous project here is how I had it configured. It looks like you are using OpenID, I did not. Not sure if this helps.
var issuer = AppSettings.Auth0Domain;
var audience = AppSettings.Auth0ClientID;
var secret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["Auth0ClientSecret"]);
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] {audience},
IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
{
new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret)
},
Provider = new Auth0AuthenticationProvider()
});
EDIT Added Auth0AuthenticationProvider
public class Auth0AuthenticationProvider : IOAuthBearerAuthenticationProvider
{
private string token;
public Task ApplyChallenge(OAuthChallengeContext context)
{
return Task.FromResult<object>(null);
}
public Task RequestToken(OAuthRequestTokenContext context)
{
token = context.Token;
return Task.FromResult<object>(null);
}
public Task ValidateIdentity(OAuthValidateIdentityContext context)
{
if (string.IsNullOrEmpty(token))
return Task.FromResult<object>(null);
var notPadded = token.Split('.')[1];
var padded = notPadded.PadRight(notPadded.Length + (4 - notPadded.Length % 4) % 4, '=');
var urlUnescaped = padded.Replace('-', '+').Replace('_', '/');
var claimsPart = Convert.FromBase64String(urlUnescaped);
var obj = JObject.Parse(Encoding.UTF8.GetString(claimsPart, 0, claimsPart.Length));
// simple, not handling specific types, arrays, etc.
foreach (var prop in obj.Properties().AsJEnumerable())
{
switch (prop.Name)
{
case "app_metadata":
SetAppMetadataClaims(context, prop.Value.ToString());
break;
}
}
return Task.FromResult<object>(null);
}
private static void SetAppMetadataClaims(OAuthValidateIdentityContext context, string jsonString)
{
var appMetadata = JsonConvert.DeserializeObject<Auth0AppMetaDataModel>(jsonString);
if(!context.Ticket.Identity.HasClaim("AccountId", appMetadata.accountId.ToString()))
context.Ticket.Identity.AddClaim(new Claim("AccountId", appMetadata.accountId.ToString()));
if (!context.Ticket.Identity.HasClaim("ClientId", appMetadata.clientId.ToString()))
context.Ticket.Identity.AddClaim(new Claim("ClientId", appMetadata.clientId.ToString()));
if (!context.Ticket.Identity.HasClaim("IsActive", appMetadata.isActive.ToString()))
context.Ticket.Identity.AddClaim(new Claim("IsActive", appMetadata.isActive.ToString()));
if (appMetadata.roles == null)
return;
foreach (var role in appMetadata.roles)
{
if (context.Ticket.Identity.HasClaim(ClaimTypes.Role, role))
continue;
context.Ticket.Identity.AddClaim(new Claim(ClaimTypes.Role, role));
}
}
}
The problem was not with Auth0 using HS256 or RS256 but instead with the base image I was using. Mono was failing silently most likely blocking the validation of my token. I have switched over to dotnet core in order to use the docker image: microsoft/dotnet:latest
My Startup file now appears like this:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseCors("CorsPolicy");
var options = new JwtBearerOptions
{
Audience = Configuration["Auth0:ApiIdentifier"],
Authority = $"https://{Configuration["Auth0:Domain"]}/"
};
app.UseJwtBearerAuthentication(options);
...
}