I need to authenticate via Android on my website (Zend Framework2+ZfcUser+ZfcUserDoctrineORM).
I want to call an url that authenticate me and return a json object that contains my session_id.
I don't know if it is the correct way but whatever i don't know how to do that with zfcUser.
David
Next, i will be able to store this session_id into Shared Preferences storage.
First of all sorry for my English.
In my application i need almost the same.
Ok. So in yoursite.com/module/YourModuleName/Module.php do:
use YourModuleName\Model\YourModuleName;
use YourModuleName\Model\YourModuleName;
class Module {
public function onBootstrap(MvcEvent $e) {
$app = $e->getApplication();
$em = $app->getEventManager();
$sm = $app->getServiceManager();
$auth = $sm->get('zfcuser_auth_service');
$model = new OrdersManager();
if (!$auth->hasIdentity()) {
$em->attach(MvcEvent::EVENT_ROUTE, function($e) use ($app, $sm, $auth, $model) {
$match = $e->getRouteMatch();
// No route, this is a 404
if (!$match instanceof RouteMatch) {
return;
}
$match = $e->getRouteMatch();
$matchParams = $match->getParams();
// $matchParams['hash'] == some url param
if (isset($matchParams['hash'])) {
$model->setDbAdapterColibo($sm->get('dbAdapter'));
$usersSqlObject = $model->getUsers();
$salt = md5('caw');
foreach ($usersSqlObject as $key => $user) {
$hash = hash('sha256', $salt.$param1.$user['user_id']);
if ($hash == $matchParams['hash']) {
$authAdapter = $sm->get('ZfcUser\Authentication\Adapter\AdapterChain');
$request = $app->getRequest();
$request->getPost()->set('identity', $user['email']);
// You may use user password to auth user
$request->getPost()->set('credential', $user['user_id']);
$result = $authAdapter->prepareForAuthentication($request);
$auth->authenticate($authAdapter);
// do your staff with session or other.
// after this you will be redirect to page from where query was
break;
}
}
}
});
}
}
}
Don`t forget about yoursite.com/module/YourModuleName/config/module.config.php
You need to add route with your URL param, to receive it in $matchParams = $match->getParams();
In case I have describe you will be auth and immediately redirect to the site.
Example:
http://example.com/someController/someAction/param1/param2/hash...
the result will be auth and open page http://example.com/someController/someAction/param1/param2/hash...
Ok. This is what i need for my app. Hope this help.
P.S. Some ideas get from Zend Framework 2 - Global check for authentication with ZFCUser
Related
How to get the following list from the Instagram account using the access token
I tried everything but not work.
here some API link which I tried before but none of them work.
I tried this one https://www.instagram.com/urvish_._/?__a=1
also this one
I tried but nothing can help me.
You can get the following (or also follower) list using the code below. Steps:
Make sure you're logged in on instagram.com
Open the API link: https://www.instagram.com/urvish_._/?__a=1 (your target username here is urvish_._)
Open the browser console: normally Ctrl+Shift+J on Windows/Linux or ⌘+Option+J on Mac
Paste this code and press Enter:
const GRAPHQL_MAX_PER_PAGE = 50;
async function getList() {
let pageLimit = 200; // from my testing
let baseInfo = JSON.parse(document.getElementsByTagName('body')[0].innerText);
let userId = baseInfo.graphql.user.id;
let config = { user_edge: 'edge_follow', query_hash: 'd04b0a864b4b54837c0d870b0e77e076', total_count: baseInfo.graphql.user.edge_follow.count };
// for followers instead of followings:
// { user_edge: 'edge_followed_by', query_hash: 'c76146de99bb02f6415203be841dd25a', total_count: baseInfo.graphql.user.edge_followed_by.count }
let after = null, hasNext = true, thisList = [];
for (pageCount = 1; hasNext && (pageCount <= pageLimit); ++pageCount) {
try {
let response = await fetch(`https://www.instagram.com/graphql/query/?query_hash=${config.query_hash}&variables=` + encodeURIComponent(JSON.stringify({
id: userId, include_reel: true, fetch_mutual: true, first: GRAPHQL_MAX_PER_PAGE, after: after
})));
if (!response.ok) {
console.warn(`Failed at page number ${pageCount.toLocaleString()}. HTTP status ${response.status}: ${response.statusText}.`);
break;
}
try {
response = await response.json();
} catch (error) {
console.error(`You may need to verify your account. Stopping. Failed at page number ${pageCount.toLocaleString()}.`, error);
break;
}
hasNext = response.data.user[config.user_edge].page_info.has_next_page
after = response.data.user[config.user_edge].page_info.end_cursor
thisList = thisList.concat(response.data.user[config.user_edge].edges.map(({ node }) => {
return {
id: node.id,
username: node.username,
full_name: node.full_name,
profile_pic_url: node.profile_pic_url,
};
}));
} catch (error) {
console.warn(`Error at page number ${pageCount.toLocaleString()}:`, error);
}
console.log(`${thisList.length.toLocaleString()} of ${config.total_count.toLocaleString()} fetched so far`);
}
console.info(`${thisList.length.toLocaleString()} fetched.`);
console.log(thisList);
}
getList()
Browser console showing a fetched list after code execution
In the code I've set the page limit to 200 so you can get up to 10,000 of your followings.
PS: For a way to visualise your lists and get more details, you can try Instagram Lists, a tool I made.
I have an ASP.NET C# MVC4 Web site that I have working wonderfully for the most part. However, when we tested on mobile, the cookies that I am using for authentication would not work. I set the Auth cookie in my controller action but when trying to access them on the next call they are not there. Once again this is ONLY A PROBLEM ON MOBILE. Works fine in desktop versions of IE, Chrome and Firefox. Does not work with Chrome on Android.
Code to write cookie (in controller action):
//Set information into object that can be read out of the cookie later
FormsAuthModel UserDataObj = new FormsAuthModel
{
UserID = dmUser.ID,
PasswordChange = dmUser.PasswordChange
};
string UserData = Convert.ToBase64String(clsShared.Serialize(UserDataObj));
//Create the ticket
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, dmUser.UserName, DateTime.Now, DateTime.Now.AddDays(1), false, UserData, FormsAuthentication.FormsCookiePath);
// Encrypt the ticket
string encTicket = FormsAuthentication.Encrypt(ticket);
// Create the cookie
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
System.Web.HttpContext.Current.Response.Cookies.Add(cookie);
Code to read cookie (in Global.asax.cs - Application_PostAuthenticateRequest):
HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
try
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
UserDataObj = (FormsAuthModel)clsShared.Deserialize(Convert.FromBase64String(authTicket.UserData), typeof(FormsAuthModel));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
//WriteEvent(string.Format("Error deserializing auth ticket - {0}", ex.Message), EventLogEntryType.Error);
}
}
The AuthCookie is always null on the subsequent requests. What the user sees is a login screen, they fill it out and they get redirected right back to the login screen.
I could not find anything in my searches that helped explain why all the mobile requests (my phone, my tablet and other users' phones) would act differently than the desktop browsers.
Any help would be greatly appreciated.
Thanks!!
OK I found a solution although I am not sure why. I changed the cookie creation code as follows and it worked.
//Set information into object that can be read out of the cookie later
FormsAuthModel UserDataObj = new FormsAuthModel
{
UserID = dmUser.ID,
PasswordChange = dmUser.PasswordChange
};
string UserData = Convert.ToBase64String(clsShared.Serialize(UserDataObj));
//Create the ticket
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, dmUser.UserName, DateTime.Now, DateTime.Now.AddDays(1), false, UserData, FormsAuthentication.FormsCookiePath);
// Encrypt the ticket
string encTicket = FormsAuthentication.Encrypt(ticket);
// Create the cookie - FIX IS HERE!!!
Response.Cookies[FormsAuthentication.FormsCookieName].Value = encTicket;
//HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
//Response.Cookies.Add(cookie);
Notice that the only change is in adding the cookie by setting the value directly instead of creating a cookie object and adding that to the collection.
i.e. - Response.Cookies["Name"] = Value;
I got the idea from this MS article: https://msdn.microsoft.com/en-us/library/ms178194.aspx.
So does anyone know why this would make a difference? I have used the cookie instance method several times before and never had this problem.
I really need your help. I am junior Joomla! developer and also junior Android developer. I am currently building an Android app for Joomla! site administration. So, where do I need help?
I managed without any problems to log in some user to frontend using this code:
// Function for user login
// return : JSON array (login : true/false; user_id : if user is loged in)
public function login() {
$post = JFactory::getApplication()->input;
$result = array();
$username = $post->get('username');
$password = $post->get('password');
$credentials = array("username" => $username, "password" => $password);
$app = JFactory::getApplication('site');
$result['login'] = $app->login($credentials);
if($result['login']) {
$result['user_id'] = JUserHelper::getUserId($username);
}
CJoomDroidHelper::postResult($result);
}
I made component named CJoomDroid which is simple web service with JSON response for every call.
For an example, when I enter:
http://some.joomla.website/index.php?option=com_cjoomdroid&view=authetication&task=login&username=user&password=pass&format=raw
, I manage to log in user to front site panel.
So no problems there, but if I want to log in to administration panel with same user using this code:
// Function for user login
// return : JSON array (login : true/false; user_id : if user is loged in)
public function login() {
$post = JFactory::getApplication()->input;
$result = array();
$username = $post->get('username');
$password = $post->get('password');
$credentials = array("username" => $username, "password" => $password);
$app = JFactory::getApplication('admin');
$result['login'] = $app->login($credentials);
if($result['login']) {
$result['user_id'] = JUserHelper::getUserId($username);
}
CJoomDroidHelper::postResult($result);
}
On this link:
http://some.joomla.website/administration/index.php?option=com_cjoomdroid&view=authetication&task=login&username=user&password=pass&format=raw
, I am getting errors. Is there any way to log in to admin panel this way?
Thanks!
Errors are like "Your session has expired; Please log in again.." etc... Android app is making call with: HttpResponse response = httpclient.execute(new HttpGet(url.toString())); , and response should be JSON object like:
{"login":true}
Automatically logging on Joomla can be very tricky.
You should give a look to this post on google groups.
There is a library named FrameworkOnFramework that enhance the power of Joomla and allows you to automatically login (via CLI or using a simple call) providing a very good protection.
I have a really weird scenario that I'm stuck on. I have a ASP.Net MVC 4 app where I'm authenticating a user and creating an authCookie and adding it to the response's cookies then redirecting them to the target page:
if (ModelState.IsValid)
{
var userAuthenticated = UserInfo.AuthenticateUser(model.UserName, model.Password);
if (userAuthenticated)
{
var userInfo = UserInfo.FindByUserName(model.UserName);
//SERIALIZE AUTHENTICATED USER
var serializer = new JavaScriptSerializer();
var serializedUser = serializer.Serialize(userInfo);
var ticket = new FormsAuthenticationTicket(1, model.UserName, DateTime.Now, DateTime.Now.AddMinutes(30), false, serializedUser);
var hash = FormsAuthentication.Encrypt(ticket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash) {Expires = ticket.Expiration};
Response.Cookies.Add(authCookie);
if (Url.IsLocalUrl(model.ReturnUrl) && model.ReturnUrl.Length > 1 && model.ReturnUrl.StartsWith("/") && !model.ReturnUrl.StartsWith("//") && !model.ReturnUrl.StartsWith("/\\"))
{
return Redirect(model.ReturnUrl);
}
var url = Url.Action("Index", "Course");
return Redirect(url);
}
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
This is working just fine in all browsers. I can login and access the secure pages in my app.
My client is requesting an android version of this app. So, I'm trying to figure out how to convert this app into an APK file. My first attempt is to create a simple index.html page with an iframe that targets the application. This works just fine in Firefox and IE 9. However, when accessing the index.html page that contains the iframe that points to the app via Chrome, I get past the login code above and the user gets redirected to the secure controller, but the secure controller has a custom attribute to make sure the user is authenticated:
public class RequiresAuthenticationAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.User.Identity.IsAuthenticated) return;
if (filterContext.HttpContext.Request.Url == null) return;
var returnUrl = filterContext.HttpContext.Request.Url.AbsolutePath;
if (!filterContext.HttpContext.Request.Browser.IsMobileDevice)
{
filterContext.HttpContext.Response.Redirect(FormsAuthentication.LoginUrl + string.Format("?ReturnUrl={0}", returnUrl), true);
}
else
{
filterContext.HttpContext.Response.Redirect("/Home/Home", true);
}
}
}
My app is failing on: filterContext.HttpContext.User.Identity.IsAuthenticated. IsAuthenticated is always false, even though the user was authenticated in the code above.
Keep in mind this only happens when accessing the app via iframe in Chrome. If I access the app directly instead of via iframe, then everything works just fine.
Any ideas?
UPDATE:
My controller extends SecureController. In the constructor of SecureController I have the code that deserializes the user:
public SecureController()
{
var context = new HttpContextWrapper(System.Web.HttpContext.Current);
if (context.Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
var serializer = new JavaScriptSerializer();
var cookie = context.Request.Cookies[FormsAuthentication.FormsCookieName].Value;
var ticket = FormsAuthentication.Decrypt(cookie);
CurrentUser = serializer.Deserialize<UserInfo>(ticket.UserData);
}
else
{
CurrentUser = new UserInfo();
}
//if ajax request and session has expired, then force re-login
if (context.Request.IsAjaxRequest() && context.Request.IsAuthenticated == false)
{
context.Response.Clear();
context.Response.StatusCode = 401;
context.Response.Flush();
}
}
First, you should be deriving from AuthorizeAttribute, not an ActionFilterAttribute. Authorization attributes execute before the method is even called at a higher level of the pipeline, while ActionFilters execute much further down, and other attributes can execute before yours.
Secondly, you aren't showing the code you use to decrypt the ticket and set the IPrincipal and IIdentity. Since that's where the problem is, it's odd that you didn't include it.
I am creating an (iphone/android) mobile app using appcelerator titanium. I have a problem using Ti.App.Properties,
I want to save the user's login data (username and password), I used Ti.App.Properties's getList and setList methods to get and set username and password at app startup. It is working fine on iPhone, but on android the data (username and password) are not retrieved at app startup.
here is the code that is executed at app startup :
var userDataArray=[{title:'name',value:''},
{title:'password',value:''}];
if(Ti.App.Properties.hasProperty("userDataArray"))
{
userDataArray = Ti.App.Properties.getList("userDataArray");
}
else
{
Ti.App.Properties.setList("userDataArray",userDataArray);
}
if((Ti.App.Properties.getList("userDataArray")[0].value.length==0)||(Ti.App.Properties.getList("userDataArray")[1].value.length==0))//check if name, password have no values.. on android, this is always the case, which is not correct
{
//go to login page
}
else if((Ti.App.Properties.getList("userDataArray")[0].value.length>0)&&(Ti.App.Properties.getList("userDataArray")[1].value.length>0))//if both username and password exist
{
//start
}
Thank you
i think your overall approach is flawed, you dont need an array just an map
// save the values as a string..
Ti.App.Properties.setString({"username":"myname", "password":"mypassword"}, "CREDENTIALS");
// retrieve the values as a string, but parse it back into an object
var credObject = JSON.parse(Ti.App.Properties.getString("CREDENTIALS"));
// dump the output
Ti.API.debug("Username "+ credObject.username);
Ti.API.debug("Password "+ credObject.password);
two remarks :
arguments for .setString() is opposite, ie Name then Value
Value must be a string, so you have to stringify() it or enter it as a string
I know this is old, but it's still relevant today as there's not a huge amount of help with Titanium. I handle this in two parts.
Part 1) After the user's credentials have been authenticated...
var username = "some username";
var password = "some password";
// Build the object and then convert it to a json string.
oCredentials = new Object();
oCredentials.username = username;
oCredentials.password = password;
var stringCredentials = JSON.stringify(oCredentials);
// Save the credentials
Ti.App.Properties.setString("Credentials", stringCredentials);
Part 2) Before you prompt the user with the login window/popup/whatever...
// Look for credentials
(function() {
var storedCredentials = Ti.App.Properties.getString("Credentials");
if (storedCredentials){
var oJson = JSON.parse(storedCredentials);
// Call your authentication function
// For example, autoAuthenticate(oJson.username, oJson.password);
} else {
// kick the user out to your login window
// For example, $.loginWindow.open();
}
})();