I try to do a email verify after registration, but with my current code, my URL is changed from "/" tot "/email/verify", but the template is not changed, I can use app with no problem . PS. I am also using VueJS. I also added MustVerifyEmail in User model, like on official doc.
PS. I receive the email registration.
web.php
Route::middleware('guest')->get('/', function () {
return redirect('/login');
});
Auth::routes(['verify' => true]);
Route::middleware(['auth', 'verified'])->get('/', function () {
return view('layouts.app');
});
Route::middleware(['auth','verified'])->get('/{any}', function () {
return view('layouts.app');
})->where('any', '.*');
Blade file
If I am auth I can access the app (Vuejs routes), else I will get another page like: registration, login, and verify with doesn't work.
#auth
<div id="app">
</div>
#else
<main class="py-4">
#yield('content')
</main>
#endauth
Auth:routes() includes all the routes that is needed in authentication. When you pass ['verify' => true] into it, it will include the email verification routes as well and that includes email/verify. Laravel do this for you.
You can refer to Laravel 5.7 Email Verification Routes
I changed the logic for blade, in the old one I checked if is auth / or guest, but I didn't check if its mail is verified.
#if(auth()->guest() || (auth()->check() && is_null(auth()->user()->email_verified_at)))
#if(url()->current() === env('APP_URL'))
<script>
window.location = "/email/verify";
</script>
#endif
<main class="py-4">
#yield('content')
</main>
#else
<div id="app">
</div>
<script src="{{mix('js/app.js')}}"></script>
#endif
Related
Given example from the docs
<button hx-post="/clicked"
hx-trigger="click"
hx-target="#parent-div"
hx-swap="outerHTML">
Click Me!
</button>
I want to change <scheme>://<netloc>/clicked to<scheme>://<netloc>/api/v1/clicked, so prepend /api/v1 into the base URL so all requests use this version. How to do that?
The only solution I can think of is to just alter the event path.
<script>
document.body.addEventListener('htmx:configRequest', (event) => {
event.detail.path = `/api/v1/${event.detail.path}`
})
</script>
I am using velusia sample, I want the client app to skip the log out prompt page, is there any specific way to achieve this, or should I implement it my self ?
How you handle logout requests is up to you. To trigger a redirection to the client application (when a post_logout_redirect_uri is set) without displaying a consent form, trigger an ASP.NET Core Logout operation pointing to OpenIddict:
// Returning a SignOutResult will ask OpenIddict to redirect the user agent
// to the post_logout_redirect_uri specified by the client application or to
// the RedirectUri specified in the authentication properties if none was set.
return SignOut(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties
{
RedirectUri = "/"
});
That said, I wouldn't recommend doing that: not requiring user consent or a form of anti-forgery protection - the id_token_hint can help, use AuthenticateAsync() to retrieve the principal from it - may make targeted DOS attacks possible.
According to your description, I suggest you could try to set a js code to automatically click the logout button in the server side.
More details, you could refer to below codes:
Modify the server's logout view as below:
#using Microsoft.Extensions.Primitives
<div class="jumbotron">
<h1>Log out</h1>
<p class="lead text-left">Are you sure you want to sign out?</p>
<form asp-controller="Authorization" asp-action="Logout" method="post">
#* Flow the request parameters so they can be received by the LogoutPost action: *#
#foreach (var parameter in Context.Request.HasFormContentType ?
(IEnumerable<KeyValuePair<string, StringValues>>) Context.Request.Form : Context.Request.Query)
{
<input type="hidden" name="#parameter.Key" value="#parameter.Value" />
}
<input class="btn btn-lg btn-success" id="Confirm" name="Confirm" type="submit" value="Yes" />
</form>
</div>
#section scripts{
<script>
$(document).ready(function() {
console.log("Fired");
document.getElementById("Confirm").click();
});
</script>
}
You can also change the HTTP method to GET instead of POST based on Velusia sample:
[HttpGet("logout")]
public async Task<IActionResult> LogoutPost()
{
await HttpContext.SignOutAsync(Clients.CmsApp);
await HttpContext.SignOutAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
return SignOut(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties
{
RedirectUri = "/"
});
}
I'm trying to build a Google signin button into my website. I'm trying to avoid using their built-in button. The code below works to sign in a user, but I can't figure out how to make my webpage remember that they're signed in when the user refreshes the page, or leaves the site and comes back.
Using Chrome's developer tools, I can see that there's an entry for https://accounts.google.com under both Local Storage and Session Storage. They seem to more or less contain the same information, including the user's validated token.
What I don't understand is how to get the gapi.auth2.init() function to recognize and use this token. The documentation doesn't seem to cover it.
<html>
<head>
<title>Login Test</title>
<script src="http://code.jquery.com/jquery-2.1.4.js"></script>
<script src="https://apis.google.com/js/platform.js?onload=renderButton" async defer></script>
</head>
<script>
var googleUser = {};
function renderButton() {
gapi.load('auth2', function(){
auth2 = gapi.auth2.init({
client_id: 'MY_CREDENTIALS.apps.googleusercontent.com',
});
attachSignin(document.getElementById('customBtn'));
});
};
function attachSignin(element) {
auth2.attachClickHandler(element, {},
function(googleUser) {
document.getElementById('name').innerText = "Signed in: " +
googleUser.getBasicProfile().getName();
}, function(error) {
alert(JSON.stringify(error, undefined, 2));
}
);
}
</script>
<body>
<div id="gSignInWrapper">
<span class="label">Sign in with:</span>
<input type="button" id="customBtn" value="Google"></input>
</div>
<p id="name"></p>
</body>
</html>
You can use listeners. This is the relevant part:
// Listen for sign-in state changes.
auth2.isSignedIn.listen(signinChanged);
// Listen for changes to current user.
auth2.currentUser.listen(userChanged);
You can also get up to date values by
var isSignedIn = auth2.isSignedIn.get();
var currentUser = auth2.currentUser.get();
To strictly detect returning users only you can do:
var auth2 = gapi.auth2.init(CONFIG);
auth2.then(function() {
// at this point initial authentication is done.
var currentUser = auth2.currentUser.get();
});
When it comes to your code I would do:
auth2 = gapi.auth2.init(CONFIG);
auth2.currentUser.listen(onUserChange);
auth2.attachClickHandler(element, {});
This way all changes in sign-in state are passed to onUserChange (this includes returning users, new sign-ins from attachClickHandler, new sign-ins from different tab).
this is a page built on example
<html>
<head>
<title>Demo: Getting an email address using the Google+ Sign-in button</title>
<style type="text/css">
html, body { margin: 0; padding: 0; }
.hide { display: none;}
.show { display: block;}
</style>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script>
<!--<script src="https://apis.google.com/js/plusone.js" type="text/javascript"></script>-->
<script src="https://apis.google.com/js/client:plusone.js" type="text/javascript"></script>
<script type="text/javascript">
/*
* Triggered when the user accepts the sign in, cancels, or closes the
* authorization dialog.
*/
function loginFinishedCallback(authResult) {
if (authResult) {
console.log('authResult : ',authResult);
if (authResult['error'] == undefined){
gapi.auth.setToken(authResult); // Store the returned token.
toggleElement('signin-button'); // Hide the sign-in button after successfully signing in the user.
getEmail(); // Trigger request to get the email address.
} else {
console.log('An error occurred');
}
} else {
console.log('Empty authResult'); // Something went wrong
}
}
/*
* Initiates the request to the userinfo endpoint to get the user's email
* address. This function relies on the gapi.auth.setToken containing a valid
* OAuth access token.
*
* When the request completes, the getEmailCallback is triggered and passed
* the result of the request.
*/
function getEmail(){
// Load the oauth2 libraries to enable the userinfo methods.
gapi.client.load('oauth2', 'v2', function() {
var request = gapi.client.oauth2.userinfo.get();
request.execute(getEmailCallback);
});
}
function getEmailCallback(obj){
var el = document.getElementById('email');
var email = '';
console.log("OBJ = ",obj)
if (obj['email']) {
email = 'Email: ' + obj['email'];
}
//console.log(obj); // Uncomment to inspect the full object.
el.innerHTML = email;
toggleElement('email');
}
function toggleElement(id) {
var el = document.getElementById(id);
if (el.getAttribute('class') == 'hide') {
el.setAttribute('class', 'show');
} else {
el.setAttribute('class', 'hide');
}
}
</script>
</head>
<body>
<div id="signin-button" class="show">
<div class="g-signin" data-callback="loginFinishedCallback"
data-approvalprompt="auto"
data-clientId="751931329576.apps.googleusercontent.com"
data-scope="https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email"
data-height="short"
data-cookiepolicy="http://semicon-equip.com"
>
</div>
<!-- In most cases, you don't want to use approvalprompt=force. Specified
here to facilitate the demo.-->
</div>
<div id="email" class="hide"></div>
</body>
</html>
Question 1: It always fails with "Uncaught TypeError: Cannot read property 'load' of undefined",
until I use
<script src="https://apis.google.com/js/client:plusone.js" type="text/javascript"></script>
instead of the example code:
<script src="https://apis.google.com/js/plusone.js" type="text/javascript"></script>
What's the difference between plusone.js and client:plusone.js ?
Question 2: Why the code run twice per page loads ?
Qestion 3: the user was logged out after he just signed in, how to fix ?
error demo page for the above (all the errors are in the background console).
This is not really an answer to the question, but a step by step procedure to reproduce it.
Below the simple html page I'm using to test (similar to the example from Ray C Lin).
I've made it as simple as possible to avoid interactions with other part of the code :
<html>
<head>
<script type="text/javascript"
src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
</head>
<body>
<input type="button" id="signOut" value="Sign out"></button>
<span id="signinButton">
<span class="g-signin"
data-accesstype="offline"
data-callback="signinCallback"
data-clientid="YOUR_CLIENT_ID_HERE"
data-cookiepolicy="single_host_origin"
data-scope="email"
</span>
</span>
<script type="text/javascript">
$('#signOut').on('click', function() {
gapi.auth.signOut();
});
function signinCallback(authResult) {
console.log("signinCallback: ", authResult);
}
(function() {
var po = document.createElement('script');
po.type = 'text/javascript';
po.async = true;
po.src = 'https://apis.google.com/js/client:plusone.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(po, s);
})();
</script>
</body>
</html>
You will have to update data-clientid with your own google client id, and display this page from an authorized javascript origin.
Please note that this might not work from localhost, as Ian suggested in a comment to this post https://plus.google.com/102746521318753162868/posts/Z5Gkro9YXVs
First, sign in using your Google account : you will see a successful callback in the console.
If you click on Sign out, you will see a callback with 'user_signed_out' in the console.
So far so good.
Sign-in again, and wait 1 hour, until the token expires (this is awful to test, as I don't know how to reduced the token lifetime).
After one hour, click on the sign out button : no callback is called.
Click on the sign-in button again :
you get a successfull callback with an authorization code and access token
immediately after, you get a 'user_signed_out' callback.
Once a session has expired, there is no way to return to a "normal" situation, you always get this second callback with 'user_signed_out'.
Actually, there is one way to return to a "normal" situation: revoke the access to the app from the google dashboard.
This is not really an issue for me as I'm using Google+ only to sign-in the user to my app using the one time authorization code, and I'm not using the access token from the client.
But this prevent automatic login from working, as the user is immediately considered as "signed out" from a google perspective.
Q1: client:plusone.js is just telling the loader to automatically load the "client" module. It's basically automatically doing gapi.load("client"), except it is already packaged up for you in one download. You could do it the other way around as well, plusone:client.js!
Q2: Not sure, it may be some JS quirk. In general, try and make your code able to handle multiple callbacks, you may get another if the state changes (e.g. the user logs out of their google account).
Q3: I don't see that on the test page - I am signed OK, and still signed in on refresh! Check you're not blocking third party cookies in your browser or similar?
i have created a page tab app for which i have set all the parameters under Auth Dialog in the app settings.
Now when i send a friend request through my app, and my friend clicks on the app request, he is able to see the authentication box describing the app and the permissions requested etc.
But if anyone visits my page on which i have added the app, and clicks on the app from there, it directly takes the user to the page tab without displaying the auth box.
Is this how it is supposed to work from a page? is it possible to display the auth box for a user coming to the app from a page?
Secondly, i have added a multi friend selector which opens by default in a popup as it is supposed to.
Is it possible to display it in the page itself instead of a popup?
I tried adding the display: 'page' option but it din work.
I have used the same code from : https://developers.facebook.com/docs/reference/dialogs/requests/
...
<body>
<div id="fb-root"></div>
<p>
<input type="button"
onclick="sendRequestToRecipients(); return false;"
value="Send Request to Users Directly" />
<input type="text" value="User ID" name="user_ids" />
</p>
<p>
<input type="button"
onclick="sendRequestViaMultiFriendSelector(); return false;"
value="Send Request to Many Users with MFS" />
</p>
<script>
window.fbAsyncInit = function() {
FB.init({
appId : XXXXXXXXXXX,
status : true,
cookie : true,
xfbml : true,
oauth : true,
});
};
(function(d){
var js, id = 'facebook-jssdk';
if (d.getElementById(id)) {
return;
}
js = d.createElement('script');
js.id = id;
js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
d.getElementsByTagName('head')[0].appendChild(js);
}(document));
</script>
<script>
function sendRequestToRecipients() {
var user_ids = document.getElementsByName("user_ids")[0].value;
FB.ui({method: 'apprequests',
message: 'My Great Request',
to: user_ids,
}, requestCallback);
}
function sendRequestViaMultiFriendSelector() {
FB.ui({method: 'apprequests',
message: 'My Great Request'
}, requestCallback);
}
function requestCallback(response) {
// Handle callback here
}
</script>
...
Any help in this regard would be very much appreciated.
Is this how it is supposed to work from a page?
Yes. Authenticated referrals don’t work when the app is accessed from a page directly.
is it possible to display the auth box for a user coming to the app from a page?
Of course – analyze the signed_request parameter, and react accordingly (meaning, display the auth dialog yourself, server- or client-side).