Identity Server 3 Reset Password Page - identityserver3

Identity Server v3 Custom Page Reset Password
I am doing the very same thing except I am working from the Mvc View Service example. I cannot figure out how I need to modify the MvcViewService and LogonWorkflowController to add the reset password page / view.
Any assist is greatly appreciated.

In MvcViewService class you have to change implementation of public Task<Stream> Login(LoginViewModel model, SignInMessage message) method.
Below code example adds two custom links to Login page:
Reset password
Register
public Task<Stream> Login(LoginViewModel model, SignInMessage message)
{
model.AdditionalLinks = new List<LoginPageLink>()
{
new LoginPageLink()
{
Text = "Reset password",
Href = "resetpassword"
},
new LoginPageLink()
{
Text = "Register",
Href = "register"
}
};
return this.GenerateStream(
model,
message,
"login",
() => this.defaultViewService.Login(model, message));
}
This is how it looks:

Related

AEM Workflow custom input data

I need to create a workflow in AEM that for a page (specified as payload) finds all the assets used on the page and uploads a list of them to an external service. So far I have most of the code ready, but business process requires me to use a special code for each of the pages (different for each run of the workflow), so that the list is uploaded to correct place.
That is when I have a question - Can you somehow add more input values for an AEM workflow? Maybe by extending the starting dialog, or adding some special step that takes user input? I need to be able to somehow specify the code when launching the workflow or during its runtime.
I have read a lot of documentation but as this is my first time using workflows, I might be missing something really obvious. I will be grateful for any piece of advice, including a link to a relevant piece of docs.
Yes, that is possible. You need to implement a dialog step in your workflow: https://docs.adobe.com/content/help/en/experience-manager-64/developing/extending-aem/extending-workflows/workflows-step-ref.html#dialog-participant-step
You could:
Create a custom menu entry somewhere in AEM (e.g. Page Editor, /apps/wcm/core/content/editor/_jcr_content/content/items/content/header/items/headerbar/items/pageinfopopover/items/list/items/<my-action>, see under libs for examples)
Create a client-library with the categories="[cq.authoring.editor]". So it is loaded as part of the page editor (and not inside the iframe with your page)
Create a JS-Listener, that opens a dialog if the menu-entry was clicked (see code). You can either use plain Coral UI dialogs, or my example misused a Granite page dialog (Granite reads the data-structure in cq:dialog, and creates a Coral UI component edit-dialog out of it - while Coral is the plain JS UI-framework)
Create a Java-Servlet, that catches your request, and creates the workflow. You could theoretically use the AEM servlet. But I often have to write my own, because it lacks some features.
Here is the JS Listener:
/*global Granite,jQuery,document,window */
(function ($, ns, channel, window) {
"use strict";
var START_WORKFLOW_ACTIVATOR_SELECTOR = ".js-editor-myexample-activator";
function onSuccess() {
ns.ui.helpers.notify({
heading: "Example Workflow",
content: "successfully started",
type: ns.ui.helpers.NOTIFICATION_TYPES.SUCCESS
});
}
function onSubmitFail(event, jqXHR) {
var errorMsg = Granite.I18n.getVar($(jqXHR.responseText).find("#Message").html());
ns.ui.helpers.notify({
heading: "Example Workflow",
content: errorMsg,
type: ns.ui.helpers.NOTIFICATION_TYPES.ERROR
});
}
function onReady() {
// add selector for special servlet to form action-url
var $form = ns.DialogFrame.currentFloatingDialog.find("form");
var action = $form.attr("action");
if (action) {
$form.attr("action", action + ".myexample-selector.html");
}
// register dialog-fail event, to show a relevant error message
$(document).on("dialog-fail", onSubmitFail);
// init your dialog here ...
}
function onClose() {
$(document).off("dialog-fail", onSubmitFail);
}
// Listen for the tap on the 'myexample' activator
channel.on("click", START_WORKFLOW_ACTIVATOR_SELECTOR, function () {
var activator = $(this);
// this is a dirty trick, to use a Granite dialog directly (point to data-structure like in cq:dialog)
var dialogUrl = Granite.HTTP.externalize("/apps/...." + Granite.author.ContentFrame.getContentPath());
var dlg = new ns.ui.Dialog({
getConfig: function () {
return {
src: dialogUrl,
loadingMode: "auto",
layout: "auto"
}
},
getRequestData: function () {
return {};
},
"onSuccess": onSuccess,
"onReady": onReady,
"onClose": onClose
});
ns.DialogFrame.openDialog(dlg);
});
}(jQuery, Granite.author, jQuery(document), window));
And here is the servlet
#Component(service = Servlet.class,
property = {
SLING_SERVLET_RESOURCE_TYPES + "=cq:Page",
SLING_SERVLET_SELECTORS + "=myexample-selector",
SLING_SERVLET_METHODS + "=POST",
SLING_SERVLET_EXTENSIONS + "=html"
})
public class RequestExampleWorkflowServlet extends SlingAllMethodsServlet {
#Override
protected void doPost(#Nonnull SlingHttpServletRequest request, #Nonnull SlingHttpServletResponse response) throws IOException {
final Page page = request.getResource().adaptTo(Page.class);
if (page != null) {
Map<String, Object> wfMetaData = new HashMap<>();
wfMetaData.put("workflowTitle", "Request Translation for " + page.getTitle());
wfMetaData.put("something", "Hello World");
try {
WorkflowSession wfSession = request.getResourceResolver().adaptTo(WorkflowSession.class);
if (wfSession != null) {
WorkflowModel wfModel = wfSession.getModel("/var/workflow/models/example-workflow");
WorkflowData wfData = wfSession.newWorkflowData(PayloadInfo.PAYLOAD_TYPE.JCR_PATH.name(), page.getPath());
wfSession.startWorkflow(wfModel, wfData, wfMetaData);
MyServletUtil.respondSlingStyleHtml(response, HttpServletResponse.SC_OK, "Triggered Example Workflow");
} else {
throw new WorkflowException("Cannot retrieve WorkflowSession");
}
} catch (WorkflowException e) {
MyServletUtil.respondSlingStyleHtml(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
}
} else {
MyServletUtil.respondSlingStyleHtml(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal error - cannot get page");
}
}
}

Xamarin.Auth Facebook login Completed event not firing

I am trying to create a Xamarin.Forms application with a Facebook login button. Everything works up until the part where the Completed event, which never gets fired.
I am using a PageRenderer to initiate the auth flow as follows:
[assembly: ExportRenderer(typeof(Page1), typeof(LoginPageRenderer))]
namespace xmrn1.Droid {
class LoginPageRenderer : PageRenderer {
private const string ClientId = "<sanitized>";
public LoginPageRenderer(Context ctx) : base(ctx) { }
protected override void OnElementChanged(ElementChangedEventArgs<Page> e) {
base.OnElementChanged(e);
var authorizeUri = new Uri("https://www.facebook.com/dialog/oauth/");
var redirectUri = new Uri($"fb{ClientId}://authorize");
var auth = new OAuth2Authenticator(
ClientId,
"email",
authorizeUri,
redirectUri);
auth.Completed += Auth_Completed;
var ui = auth.GetUI(Context);
Context.StartActivity(ui);
}
private void Auth_Completed(object sender, AuthenticatorCompletedEventArgs e) {
// This never gets called
}
}
}
And this is my "Facebook Login" settings:
And my "Advanced Settings" settings:
Found the answer, I had to turn on the Web OAuth Login in the Facebook Login settings, and also to change the redirectUri to some uri in my domain, and add that uri to the Valid OAuth Redirect URIs in that same settings window.
Strange thing though, now when I log in, and the two-factor-authentication code prompt shows up, my phone displays an authenticator popup notification asking me to approve and when I press "Yes" it doesn't automatically confirm the login, I have to manually type the 2fa code anyway...

converse.js : How can I pre-populate the Username field in the login form

I have tried this:
<script>
converse.initialize({
websocket_url: 'wss://xxx.xxx.xxx/websocket',
jid:'xxxxx#xxxx.xxx.xxx',
show_controlbox_by_default: true,
view_mode: 'overlayed' });
</script>
I was hoping this would display a login form with the Username field already populated with the value given in jid. However converse.js still displays an empty field with the default placeholder.
I'm using "https://cdn.conversejs.org/4.0.1/dist/converse.min.js"
OK so I'm not a javascript programmer but the solution I've come up with is to modify the renderLoginPanel() function and add the following
renderLoginPanel() {
this.el.classList.add("logged-out");
if (_.isNil(this.loginpanel)) {
this.loginpanel = new _converse.LoginPanel({
'model': new _converse.LoginPanelModel()
});
const panes = this.el.querySelector('.controlbox-panes');
panes.innerHTML = '';
panes.appendChild(this.loginpanel.render().el);
this.insertBrandHeading();
} else {
this.loginpanel.render();
}
/* ***Add this line to pre-populate the username field*** */
document.getElementById("converse-login-jid").value = _converse.jid;
this.loginpanel.initPopovers();
return this;
},
I'd be interested to hear if this is anywhere near a good solution.

CQ-Dialog page properties can not be stored from site admin but works from sidekick

The purpose of the following function is to allow the user to save the edited page properties in the CQ-Dialog even though if they invalid by clicking on the button save anyway:
PageProperties.showMsg = function(dialog, config, errorMessage) {
CQ.Ext.MessageBox.buttonText.ok = "save anyway";
CQ.Ext.Msg.show({
title : "Completeness check failed",
msg : errorMessage,
buttons: CQ.Ext.Msg.OKCANCEL,
fn : function(buttons) {
if(buttons == "ok") {
dialog.form.items.each(function(field) {
// clear fields with emptyText so emptyText is not submitted
if (field.emptyText && field.el && field.el.dom && field.el.dom.value == field.emptyText) {
field.setRawValue("");
}
});
var action = new CQ.form.SlingSubmitAction(dialog.form, config);
dialog.form.isValid = function() {
return true;
};
dialog.form.doAction(action);
dialog[dialog.closeAction]();
CQ.Util.reload();
}
}
});
};
This functions works fine from the sidekick. When I click on save anyway all current values of the page properites are stored regardless if they are valid or not. This does not work from the site admin. when I call the page properties of the same page from the site admin and try to save the page properties with invalid values by clicking on save anyway, this does not works (old values are stored and nothing changes).
I hope somebody can help. thank you
I found the solution. the problem was the function CQ.Util.reload(). It prevent storing the values

Area in MVC3- RedirectToAction is not working as expected

I have an area called coverage.The routing is like
context.MapRoute(
"CoverageSummary", // Route name
"Coverage/Summary/{policyId}", // URL with parameters
new { controller = "Coverage", action = "Summary", policyId = UrlParameter.Optional }, // Parameter defaults
new string[] { "Web.Mvc.Claims.Areas.Coverage.Controllers" }
);
when I acess the page Mysite/Coverage/Summary/10 it shows a page. fine.
But in an Action methode i have code as below
return RedirectToAction("Summary","Coverage", new RouteValueDictionary(new { policyID = 10 }));
but this is not loading the page Mysite/Coverage/Summary/10 .
it is showing 404 error.
if i refresh the page still it give 404.but if i cut and past the same url in address bar and hit enter it works
What can be the reason
Try with area property in your RouteValueDicitionary
return RedirectToAction("Summary","Coverage", new RouteValueDictionary(new { policyID = 10, area = "Your_Area_Name" }));