Keycloak ui_locales is ignored on requesting password reset link - keycloak

I am passing a chosen language from my web app into the keycloak login ui with keyCloakClient.createLoginUrl({locale: locale}) which correctly redirects me to: https://localhost/auth/realms/../protocol/openid-connect/auth?....&ui_locales=it. This shows me the content correctly in locale it.
For the password-reset link shown in the login form, I also added ui_locales=it to the url, which redirects me to: https://localhost/auth/realms/../login-actions/reset-credentials?....&ui_locales=it. This also shows me the content correctly in locale it.
Problem:
When I add ui_locales=it to the submission url for submitting the reset-password-request (${url.loginAction?no_esc} in login-reset-password.ftl, that generates the url https://localhost/auth/realms/../login-actions/reset-credentials?..), and I submit the form, I land on: https://localhost/auth/realms/../login-actions/authenticate?execution=.... This suddenly has no ui_locales in the url, and the content is therefore not translated in locale it.
To test if there are any magic redirections, i logged the network with preserve-log enabled. It shows only one new entry after clicking the reset-password-request button: https://localhost/auth/realms/../login-actions/reset-credentials?...&ui_locales=it.
Any ideas?
EDIT:
The same issue happens when submitting the login form with wrong credentials, to the action url (${url.loginAction?no_esc}) with appended &ui_locales=it.
It seems that locale query parameter is buggy since a while see Why are kc_locale and UI lang switch not working?. According to https://www.keycloak.org/docs/latest/release_notes/, in 9.0 was a change for locale, and was reverted in 9.0.1. Since then, there was no new change for locale. I am using 12.0.4.
Cookie approach:
I created the Cookie KEYCLOAK_LOCALE with JS on my React Login GUI, passing the locale value from the URL. It works only until a user logs in the very first time. Because then, Keycloak somehow sets the same Cookie with httpOnly, so that I can't read/write the Cookie value anymore with JS. So I can't overwrite the Cookie value on a new login, and I can't read the Cookie value to sync it with the React GUI localization.
Working usecase: Choose language in App -> redirect to Keycloak login -> set KEYCLOAK_LOCALE Cookie with value from the url (Keycloak & GUI language stay in sync now) -> go back to App -> change language in App -> redirect to Keycloak login -> Keycloak language can be updated over the Cookie with js because Cookie is not httpOnly.
Not working usecase: Choose language in App -> redirect to Keycloak login -> set KEYCLOAK_LOCALE Cookie with value from the url (Keycloak & GUI language stay in sync now) -> login -> Keycloak updates the Cookie to be httpOnly -> redirect back to App happens -> logout -> change language in App -> redirect to Keycloak login -> Keycloak language can't be updated over the Cookie with js because Cookie is httpOnly.

I fix it by setting the cookie in template.ftl manually before reloading the page.
let me know if you need more support.
document.addEventListener("DOMContentLoaded", function() {
let locales = 'ui_locales';
document.getElementById("lang-link").addEventListener("click", function() {
let switchTo = ...
document.cookie = 'KEYCLOAK_LOCALE=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;'
document.cookie = 'KEYCLOAK_LOCALE='+ switchTo;
// change the language
const currentUrl = new URL(window.location.href);
currentUrl.searchParams.set(locales, switchTo);
document.location.href = currentUrl;
});
});
```

I've added this snippet to my code:
<script type="text/javascript">
(function() {
if ('URLSearchParams' in window) {
let parameters = new URLSearchParams(location.search);
let locale = parameters.get('ui_locales');
if (locale != null) {
let [language, country] = locale.split('-');
document.cookie = "KEYCLOAK_LOCALE=" + language + "; path=/;";
}
}
})();
</script>
Now on login page load i set KEYCLOAK_LOCALE from ui_locales parameter

Related

How to redirect to home page in kentico after login in site intead Admin/cmsadministration.aspx?

I'm trying to redirect the users to home page after to log in. I've already added default target URL in the web part also in the template, I tried also by code
else if (!String.IsNullOrEmpty(DefaultTargetUrl))
{
redirectUrl = ResolveUrl("~/Compliance.aspx");
}
I also add a new domain alias with a default alias path but nothing is working.
Instead of using ~/admin as the login page, create your own ~/login page, that can be redirected to anywhere. If you use the default ~/admin it result to /CMSPages/logon.aspx?ReturnUrl=%2fKentico11%2fAdmin%2fcmsadministration.aspx which return URL is the Admin/cmsadministration.aspx

Actions on Google implicit account linking works in simulator/browser, but not on device (via Google Home app)

I've implemented the implicit flow for Actions on Google account linking, and am using Dialogflow (previously API.AI) to define intents.
The full flow works in the device simulator (from AOG). The first intent gets a "It looks like your account isn't linked yet..." response, and the debug pane includes a URL to initiate linking:
https://assistant.google.com/services/auth/handoffs/auth/start?account_name=[account]#gmail.com&provider=[project_id]_dev&scopes=email&return_url=https://www.google.com/
If I follow this URI in a cache-less window:
I'm redirected to my app's authentication page
I choose to sign in with my Google account (same as [account] above)
I'm redirected to google.com with a success message in the URI bar
The simulator now accepts actions via my app and responds correctly
However, if I follow the same flow using a physical Google Home & the gH app for Android.
Device tells me account not yet linked
Open Google home and follow 'Link to [my app]' link
Browser opens to authentication page
Sign in as user
Redirected to a white page with a single link "Return to app", which has an href: about:invalid#zClosurez
Linking was unsuccessful, so additional attempts to run intents on the Google Home get the same "Account not yet linked" response.
I've inspected the intermediate access_token and state variables at length, and they all match and look to be correctly formatted:
Authentication URL (app sign in page): https://flowdash.co/auth/google?response_type=token&client_id=[client_id]&redirect_uri=https://oauth-redirect.googleusercontent.com/r/[project_id]&scope=email&state=[state]
After authenticating, redirected to (this is the white screen with 'return to app' broken link): https://oauth-redirect.googleusercontent.com/r/genzai-app#access_token=[token]&token_type=bearer&state=[state]
So, it seems there's something non-parallel about the way the simulator and physical devices work in terms of implicit flow account linking.
I've been struggling with this, and with the AOG support team for a very long time to no avail. Anyone else see a similar issue?
Updated with response redirect code:
Login handled by react-google-login component with profile & email scopes. On success we call:
finish_auth(id_token) {
let provider = {
uri: '/api/auth/google_auth',
params: ['client_id', 'redirect_uri', 'state', 'response_type'],
name: "Google Assistant"
}
if (provider) {
let data = {};
provider.params.forEach((p) => {
data[p] = this.props.location.query[p];
});
if (id_token) data.id_token = id_token;
api.post(provider.uri, data, (res) => {
if (res.redirect) window.location = res.redirect;
else if (res.error) toastr.error(res.error);
});
} else {
toastr.error("Provider not found");
}
}
provider.uri hits this API endpoint:
def google_auth(self):
client_id = self.request.get('client_id')
redirect_uri = self.request.get('redirect_uri')
state = self.request.get('state')
id_token = self.request.get('id_token')
redir_url = user = None
if client_id == DF_CLIENT_ID:
# Part of Google Home / API.AI auth flow
if redirect_uri == "https://oauth-redirect.googleusercontent.com/r/%s" % secrets.GOOGLE_PROJECT_ID:
if not user:
ok, _email, name = self.validate_google_id_token(id_token)
if ok:
user = User.GetByEmail(_email, create_if_missing=True, name=name)
if user:
access_token = user.aes_access_token(client_id=DF_CLIENT_ID)
redir_url = 'https://oauth-redirect.googleusercontent.com/r/%s#' % secrets.GOOGLE_PROJECT_ID
redir_url += urllib.urlencode({
'access_token': access_token,
'token_type': 'bearer',
'state': state
})
self.success = True
else:
self.message = "Malformed"
else:
self.message = "Malformed"
self.set_response({'redirect': redir_url}, debug=True)
I am able to make it work after a long time. We have to enable the webhook first and we can see how to enable the webhook in the dialog flow fulfillment docs If we are going to use Google Assistant, then we have to enable the Google Assistant Integration in the integrations first. Then follow the steps mentioned below for the Account Linking in actions on google:-
Go to google cloud console -> APIsand Services -> Credentials -> OAuth 2.0 client IDs -> Web client -> Note the client ID, client secret from there -> Download JSON - from json note down the project id, auth_uri, token_uri -> Authorised Redirect URIs -> White list our app's URL -> in this URL fixed part is https://oauth-redirect.googleusercontent.com/r/ and append the project id in the URL -> Save the changes
Actions on Google -> Account linking setup 1. Grant type = Authorisation code 2. Client info 1. Fill up client id,client secrtet, auth_uri, token_uri 2. Enter the auth uri as https://www.googleapis.com/auth and token_uri as https://www.googleapis.com/token 3. Save and run 4. It will show an error while running on the google assistant, but dont worry 5. Come back to the account linking section in the assistant settings and enter auth_uri as https://accounts.google.com/o/oauth2/auth and token_uri as https://accounts.google.com/o/oauth2/token 6. Put the scopes as https://www.googleapis.com/auth/userinfo.profile and https://www.googleapis.com/auth/userinfo.email and weare good to go. 7. Save the changes.
In the hosting server(heroku)logs, we can see the access token value and through access token, we can get the details regarding the email address.
Append the access token to this link "https://www.googleapis.com/oauth2/v1/userinfo?access_token=" and we can get the required details in the resulting json page.
`accessToken = req.get("originalRequest").get("data").get("user").get("accessToken")
r = requests.get(link)
print("Email Id= " + r.json()["email"])
print("Name= " + r.json()["name"])`
Not sure which python middleware or modules you are using but
self.set_response({'redirect': redir_url}, debug=True)
seems to be setting parameters for a returning a response which isn't correct. Instead you should redirect your response to the redirect_url. For example importing the redirect module in Flask or Django like:
from flask import redirect or from django.shortcuts import redirect
then redirect like:
return redirect(redirect_url)
It appears Google has made a change that has partially solved this problem in that it is now possible to complete the implicit account linking flow outside of the simulator, in the way outlined in my question.
It seems the problem stemmed from an odd handling (on the AOG side) of the client-side redirect case used after sign in with the Google sign-in button.
From Jeff Craig in this thread:
The current workaround, where we provide the "Return to app" link
currently what we're able to provide. The issue is with the way that
redirecting to custom-scheme URIs is handled in Chrome, specifically,
with regard to the redirect happening in the context of a user action.
XHR will break that context, so what is happening is that you click
the Google Sign-In Button, which triggers an XHR to Google's servers,
and then you (most likely) do a client-side redirect back to the
redirect_url we supply, our handler executes, and isn't able to do a
JS redirect to the custom scheme URI of the app, because were outside
of the context of a direct user click.
This is more of a problem with the Implicit (response_type=token) flow
than with the authorization code (response_type=code) flow, and the
"Return to app" link is the best fallback case we currently have,
though we are always looking for better solutions here as well.
The current behavior shows the 'Return to app' link, but as of last week, this link's href is no longer about:invalid#zClosurez, but instead successfully completes the sign-in and linking process. It's an odd and confusing UX that I hope Google will improve in the future, but it was sufficient to get my app approved by the AOG team without any changes to my flow.

Redirect URI hasn't updated

I have a Meteor app and am using the following function to login with facebook
fbLogin = function() {
Meteor.loginWithFacebook({
requestPermissions: ['public_profile', 'email', 'user_location']
}, function(err) {
if (err)
// redirect to register if popup comes and user isn't on register
Session.set('errorMessage', err.reason || 'Unknown Eror');
console.log(Session.get('errorMessage'));
});
}
The credentials are set and working properly ( app id and secret)
Recently, I updated my Facebook app settings with a new Domain and Site url and yet it does not let me login. It throw the:
Given URL is not allowed by the Application configuration: One or more of the given URLs is not allowed by the App's settings. It must match the Website URL or Canvas URL, or the domain must be a subdomain of one of the App's domains.
error with the redirect_uri parameter in the url set to the old site url
Is there possibly a delay on Facebook's end or some other issue at hand?
This can happen when the redirect_uri submitted with the https://www.facebook.com/dialog/oauth request is not present in the list of Valid OAuth redirect URIs under:
Settings >> Advanced >> Security
add a redirect_uri like https://www.facebook.com/connect/login_success.html as an example

Error redirecting to specfic page after Smartsheet Auth

#RequestMapping(value = "/smartsheet.htm", method= RequestMethod.GET)
public void smartSheetAuth(HttpServletRequest req,HttpServletResponse resp,HttpSession session){
String userEmail = ************;
StringBuilder authUrl = new StringBuilder();
authUrl.append("https://app.smartsheet.com/b/orgsso/");
authUrl.append(gPlusUser.getDomain());
/*
authUrl.append("?loginEmail=");
authUrl.append(userEmail);*/
oauth = new OAuthFlowBuilder()
.setAuthorizationURL(authUrl.toString())
.setClientId(EnvironmentVariables.SMARTSHEET_CLIENT_ID)
.setClientSecret(EnvironmentVariables.SMARTSHEET_CLIENT_SECRET)
.setRedirectURL( APPLICATION_BASE_URL + RequestMapping value to be redirected to)
.build();
EnumSet<AccessScope> smartsheetAccessScopes = EnumSet.of(AccessScope.READ_SHEETS,AccessScope.SHARE_SHEETS);
String url = oauth.newAuthorizationURL(smartsheetAccessScopes, "MY_STATE");
System.out.println("url >>>"+url);
resp.sendRedirect(url);
}
What I am trying to do is Organizational Login . But, after I am authenticated instead of going to the redirect url specified in OAuthFlowBuilder ,it takes me to my home page of smartsheet. If I dont setAuthorizationURL() , I have to select the Oraganization Login from the options. It kinda works, but what I am trying to achieve is to get directly to SSO login page instead of clicking organization login option and then going further.
I have made an app using developer tools option of smartsheet and mentioned the same redirect url there also. Nothing seems to work.
Now redirect url is optional , but if dont specify that I am prompted with IllegalStateException.
Using smartsheet-sdk-java-2.0.0.jar
The flow that you're trying to achieve is not possible. i.e., https://app.smartsheet.com/b/orgsso/ is not a valid authorization URL for Smartsheet oAuth.
Instead (as described in the Smartsheet oAuth documentation), you must use this URL: https://app.smartsheet.com/b/authorize. From there, the user can select the appropriate option to specify how they'd like to login.

Facebook Secure Forms

I am building some forms using the html input tabs in Facebook.
My form actions are post and insert linking to externally hosted php
function files.
The problem is, if the user isn't using Facebook's new https setting, a pop up
is shown with "un secure form"
Is there a why to provide a secure handler externally hosted or is this something
I would have go deeper into Facebook ap making with?
Facebook loads your app into an iframe (using POSTing a form).
When the user is using https with facebook they use the Secure Canvas URL property from the app settings, and when the user is not on secure browsing they use the Canvas URL.
Because of that, your page is not loaded from https but http, which is why that warning is shown to the user by the browser.
What you can do is to check when your page is loading which protocol is used and if it's not https then reload the page from https.
Something like (using window.location object):
var location = window.location;
if (location.protocol != "https:") {
window.location.href = "https://" + location.host + "/" + location.pathname + location.search
}
Or if you don't expect to have urls in your querystring you can simply replace:
window.location.href = window.location.href.replace("http", "https");