Ory Kratos setup process where password cannot be changed successfully
P粉776412597
2023-08-31 18:45:58
<p>I created my own user interface for the Ory Kratos setup process. The problem I'm having is that although the message comes back that my settings have been updated successfully, my new password isn't reflected and I haven't successfully recovered my account. Below is the code snippet I use to render the UI using Vue 3. </p>
<pre class="brush:js;toolbar:false;">// SettingsVue.vue
<template>
<div id="settings">
<HomeTopbar :views="[]" />
<div class="settings-wrapper">
<h1 class="poppins fs_3 fw_6">Recover your password</h1>
<OryFlow v-if="settingsFlow"
:flow="settingsFlow"
title="Login"
form-id="settings-form"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
/* ory */
import { injectStrict } from '@/utils';
import { $ory } from '@/plugins/ory';
import { makeHandleGetFlowError } from '@/utils/flows';
/* types */
import type { SelfServiceSettingsFlow } from '@ory/kratos-client';
/* composables */
import { useRoute, useRouter } from 'vue-router';
/* components */
import OryFlow from '@/components/flows/OryFlow.vue';
import HomeTopbar from '@/components/ui/HomeTopbar.vue';
const ory = injectStrict($ory);
const route = useRoute();
const router = useRouter();
const settingsFlow = ref<SelfServiceSettingsFlow | undefined>();
const handleGetFlowError = makeHandleGetFlowError(router);
// check if we have a flow param
const { flow } = route.query;
const initializeSelfServiceSettingsFlowForBrowsers = () =>
ory
.initializeSelfServiceSettingsFlowForBrowsers()
.then((response) => {
settingsFlow.value = response.data;
router.replace({
query: {
flow: response.data.id,
},
});
})
.catch(handleGetFlowError);
if (typeof flow !== 'string') {
// if there's no flow in our route,
// we need to initialize our login flow
initializeSelfServiceSettingsFlowForBrowsers();
} else {
ory
.getSelfServiceSettingsFlow(flow)
.then((response) => {
settingsFlow.value = response.data;
})
.catch(handleGetFlowError);
}
</script>
<style scoped lang="scss">
#settings {
width: 100%;
height: 100%;
.settings-wrapper {
margin: var(--space-5) auto 0 auto;
padding: 0 var(--space-3);
margin-top: var(--space-4);
width: 300px;
}
}
</style>
</pre>
<pre class="brush:js;toolbar:false;">#OryFlow.vue
<template>
<div class="ory-flow">
<form :id="formId" :action="flow.ui.action" :method="flow.ui.method">
<OryUiNode v-for="node in flow.ui.nodes"
:key="getNodeId(node)"
:id="getNodeId(node)"
:node="node"
class="ui-node"
/>
</form>
<div class="messages" v-if="flow.ui.messages">
<OryUiMessage v-for="message in flow.ui.messages" :message="message" />
</div>
</div>
</template>
<script setup lang="ts">
import type {
SelfServiceLoginFlow,
SelfServiceRegistrationFlow,
SelfServiceRecoveryFlow,
SelfServiceSettingsFlow,
SelfServiceVerificationFlow,
} from '@ory/kratos-client';
import OryUiNode from './OryUiNode.vue';
import OryUiMessage from './OryUiMessage.vue';
import { getNodeId } from '@ory/integrations/ui';
defineProps<{
flow:
| SelfServiceLoginFlow
| SelfServiceRegistrationFlow
| SelfServiceRecoveryFlow
| SelfServiceSettingsFlow
| SelfServiceVerificationFlow;
formId?: string;
}>();
</script>
<style scoped lang="scss">
.ui-node .ui-node {
margin-top: var(--space-2);
}
.message {
margin-top: var(--space-2);
}
</style>
</pre>
So solving this problem is actually pretty straightforward and obvious, which became apparent after I reviewed the source code for the React Self-Service UI created and maintained by the Ory team.
If you submit all UI node groups together into the same form, it will only execute on the
default
group and one other group. In my case, after successfully processing theprofile
group, it ignored thepassword
group. The solution I followed is basically the same as the one provided in the repository I mentioned in the previous paragraph. Implement a filtering mechanism that allows you to use two separate forms to separate the values when the form is submitted. Remember that you must always submit thedefault
group as it includes your CSRF token .Here is the updated code that solved my problem:
First, add support for the
:only
attribute for filtering nodes:Next, use this new attribute in a form to filter only the node groups
password
anddefault
. You can use the same method to filterprofile
anddefault
in another form.