Interacting with the STS Endpoint
We are moving some prior discussion to a new thread. Here are the relevant posts: Anthony Says: Notice Register or Reset is the Action/Request AuthN is a phase in the request evaluation. For the most part, they are the same... basically Initiate some kind of request get AuthNRequiredFault RST RSTR more RSTR till u get the token resume the original request with that token for PasswordReset u have the following get AnonymousInteractionRequiredFault when u resume do a Create (with the new pwd)on the new endpoint u will either get DataRequiredFault or a success message in case u get DataRequiredFault, might be able to retry the Create (depending on the error is recoverable or not) Basically if u can get the AuthN part, u are 90% done with the SSPR client Jeremy Says: Hi Anthony. Can you give me a little push in the right direction on getting the STS client working? I have used svcutil to download the basic code for the Client. I was hoping that the FIM STS would implement the IWSTrustChannelContract so I could leverage the .Issue message. I couldn't figure out how to make that work. So now I am trying to form a message to the STS as shown here: http://msdn.microsoft.com/en-us/library/ee652302(VS.100).aspx I can't figure out how to add the Security header. I am sure this is dead-simple but the learing curve for WCF is steep. Thanks for the help! Anthony Says: ar... we are trying to pull that MSDN doc... the content isn't too accurate. I suggest you do a SSPR registration using the FIM client and capture the message trace. Jeremy Says: I think I am on my way again: byte[] entropy = Guid.NewGuid().ToByteArray(); RequestSecurityToken rst = new RequestSecurityToken(Microsoft.IdentityModel.SecurityTokenService.RequestTypes.Issue); rst.AppliesTo = new EndpointAddress(endpointAddress); rst.Entropy = new Entropy(entropy as byte[]); rst.ActAs = new Microsoft.IdentityModel.Tokens.SecurityTokenElement(new UserNameSecurityToken("FIMDEMO\\userthree", String.Empty)); WSTrustFeb2005RequestSerializer test = new WSTrustFeb2005RequestSerializer(); WSTrustSerializationContext sc = new WSTrustSerializationContext(); WSTrustRequestBodyWriter bw = new WSTrustRequestBodyWriter(rst,test,sc); SecurityTokenElement securityElement; securityElement = new SecurityTokenElement(new UserNameSecurityToken("FIMDEMO\\userthree",String.Empty)); EnvelopeVersion ev = EnvelopeVersion.Soap12; MessageVersion mv = MessageVersion.CreateVersion(EnvelopeVersion.Soap11,AddressingVersion.WSAddressingAugust2004); Message request = Message.CreateMessage(mv, Constants.WsTrust.RequestSecurityTokenIssueAction, bw); return request; Anthony Says: let's... start a new thread... :) this thread has been answered and it's a bit hard for me to follow.... And i strongly encourage u to first capture the trace first... Then u will realize ActAs, AppliesTo, etc are not needed (if things haven't changed)... What it really matters is the Entropy and the Context And for that exact reason, i pretty much just use XMLSerializer and come up with about 10 very simple class just to construct the XML... then i don't need to worry about the inconsistency in format... and to be honest with u, i didn't even bother looking at the WS* class in .net
April 1st, 2010 3:01am

let us know if u have any progress?The FIM Password Reset Blog http://blogs.technet.com/aho/
Free Windows Admin Tool Kit Click here and download it now
April 1st, 2010 3:04am

OK, I have done the trace. Here is the AuthN Fault from the STS: <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"><s:Header><a:Action s:mustUnderstand="1" u:Id="_4" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:a="http://www.w3.org/2005/08/addressing">http://schemas.microsoft.com/2006/11/ResourceManagement/fault</a:Action><a:RelatesTo u:Id="_5" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:a="http://www.w3.org/2005/08/addressing">urn:uuid:f37a3c83-e535-481a-bf43-f10138574870</a:RelatesTo><Context u:Id="_6" xmlns="http://schemas.microsoft.com/ws/2006/05/context" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><Property name="instanceId">b860359a-7819-4c41-a23c-2eb55641bd3f</Property></Context> .....Other Header stuff removed.... <s:Body u:Id="_2" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><Fault xmlns="http://www.w3.org/2003/05/soap-envelope"><Code><Value>Sender</Value><Subcode><Value xmlns:a="http://schemas.microsoft.com/2006/11/ResourceManagement">a:AuthenticationRequiredFault</Value></Subcode></Code><Reason><Text xml:lang="en-US">Authentication information is required</Text></Reason><Detail><AuthenticationRequiredFault xmlns="http://schemas.microsoft.com/2006/11/ResourceManagement" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><SecurityTokenServiceAddress>http://fim02.fimdemo.local:5726/ResourceManagementService/SecurityTokenService/Registration</SecurityTokenServiceAddress><UserRegistered>true</UserRegistered><UserLockedOut>false</UserLockedOut></AuthenticationRequiredFault></Detail></Fault></s:Body></s:Envelope> The correct response to this from the client appears to be: <s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope"><s:Header><a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action><a:MessageID>urn:uuid:7cae7b8b-d200-4900-bb16-72ca008987a9</a:MessageID><a:ReplyTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo></s:Header><s:Body><RequestSecurityToken Context="b860359a-7819-4c41-a23c-2eb55641bd3f" xmlns="http://schemas.xmlsoap.org/ws/2005/02/trust"><Entropy><!-- Removed--></Entropy></RequestSecurityToken></s:Body></s:Envelope> My first roadblock is that the AuthenticationRequiredFault in the default client exposes the Context field but it doesn't work properly. I tried using Svcutil to connect to the ResourceManagement MEX and re-download the code for this object but that did not work either. So question 1 is, what is the best way to get the Context out of the fault? Question 2 is around your next statement about using some custom object classes and the ObjectSerializer to simplify everything. Could you share some sample code for your RequestSecurityToken object and how you go about using the ObjectSerializer to end up with a Message that can be sent to the emdpoint? Once I have the pattern for that down I should be able to replicate that for the other requests.
April 1st, 2010 3:18am

to get the context: Message rstResponse = RequestSecurityToken(rstRequest); if (rstResponse.IsFault) { ClientHelper.HandleFault(rstResponse); } RequestSecurityTokenResponse response = rstResponse.GetBody<RequestSecurityTokenResponse>(new ClientSerializer(typeof(RequestSecurityTokenResponse))); ContextMessageProperty currentContext; if (ContextMessageProperty.TryGet(rstResponse.Properties, out currentContext)) { response.CurrentContext = currentContext; } ============================================= [XmlRoot(Namespace = Constants.WsTrust.Namespace)] public class RequestSecurityToken { const short DEFAULT_KEY_SIZE = 256; int lockInt; public RequestSecurityToken() { // code removed } [XmlAttribute()] public String Context; [XmlElement(Namespace = Constants.WsPolicy.Namespace)] public Entropy Entropy; } [XmlRoot(Namespace=Constants.WsPolicy.Namespace)] public class Entropy { [XmlElement(Namespace=Constants.WsTrust.Namespace)] public byte[] BinarySecret; } public RequestSecurityTokenResponse RequestSecurityToken(RequestSecurityToken request) { if (request == null) { throw new ArgumentNullException("request"); } Message rstRequest = Message.CreateMessage(MessageVersion.Default, Constants.WsTrust.RequestSecurityTokenIssueAction, request, new ClientSerializer(typeof(RequestSecurityToken))); Message rstResponse = RequestSecurityToken(rstRequest); if (rstResponse.IsFault) { ClientHelper.HandleFault(rstResponse); } ......The FIM Password Reset Blog http://blogs.technet.com/aho/
Free Windows Admin Tool Kit Click here and download it now
April 1st, 2010 9:29am

i also want to point out that the Context manipulation in the client u based on is buggy. It should always use ContextMessageProperty. Adding generating the exact soap message might not work if u are not using ContextMessageProperty. took me a long time to figure that one out... >_<"
April 1st, 2010 11:37am

OK, Still not working yet. I Put to the Alternate Endpoint. The Alternate Endpoint returns an Authentication Fault. Here is the message: <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> <s:Header> <a:Action s:mustUnderstand="1" u:Id="_4">http://schemas.microsoft.com/2006/11/ResourceManagement/fault</a:Action> <a:RelatesTo u:Id="_5">urn:uuid:cf54f375-c5c1-49af-aa9f-e3a3ad9cc9d3</a:RelatesTo> <Context u:Id="_6" xmlns="http://schemas.microsoft.com/ws/2006/05/context"> <Property name="instanceId">ee1c1fe5-898d-4335-8cd1-a94bc4bcacd1</Property> </Context> <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> <u:Timestamp u:Id="uuid-7b42f5dc-4599-4d6b-9863-ad7facc9d3db-114"> <u:Created>2010-04-03T03:36:48.572Z</u:Created> <u:Expires>2010-04-03T03:41:48.572Z</u:Expires> </u:Timestamp> <c:DerivedKeyToken u:Id="_0" xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc"> <o:SecurityTokenReference> <o:Reference URI="urn:uuid:6690b5e3-9623-4c60-b5b6-07c71258a4ae" ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct" /> </o:SecurityTokenReference> <c:Offset>0</c:Offset> <c:Length>24</c:Length> <c:Nonce>6RJO89lrk2uWGuOFNToa4A==</c:Nonce> </c:DerivedKeyToken> <c:DerivedKeyToken u:Id="_1" xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc"> <o:SecurityTokenReference> <o:Reference URI="urn:uuid:6690b5e3-9623-4c60-b5b6-07c71258a4ae" ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct" /> </o:SecurityTokenReference> <c:Nonce>t8yhy/3IuyDpCqjyk/3VUA==</c:Nonce> </c:DerivedKeyToken> <e:ReferenceList xmlns:e="http://www.w3.org/2001/04/xmlenc#"> <e:DataReference URI="#_3" /> <e:DataReference URI="#_7" /> </e:ReferenceList> <e:EncryptedData Id="_7" Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:e="http://www.w3.org/2001/04/xmlenc#"> <e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" /> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <o:SecurityTokenReference> <o:Reference URI="#_1" /> </o:SecurityTokenReference> </KeyInfo> <e:CipherData> <e:CipherValue>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</e:CipherValue> </e:CipherData> </e:EncryptedData> </o:Security> </s:Header> <s:Body u:Id="_2"> <Fault xmlns="http://www.w3.org/2003/05/soap-envelope"> <Code> <Value>Sender</Value> <Subcode> <Value xmlns:a="http://schemas.microsoft.com/2006/11/ResourceManagement">a:AuthenticationRequiredFault</Value> </Subcode> </Code> <Reason> <Text xml:lang="en-US">Authentication information is required</Text> </Reason> <Detail> <AuthenticationRequiredFault xmlns="http://schemas.microsoft.com/2006/11/ResourceManagement" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <SecurityTokenServiceAddress>http://fim02.fimdemo.local:5726/ResourceManagementService/SecurityTokenService/Registration</SecurityTokenServiceAddress> <UserRegistered>true</UserRegistered> <UserLockedOut>false</UserLockedOut> </AuthenticationRequiredFault> </Detail> </Fault> </s:Body></s:Envelope> From this message I try to retrieve the context: ContextMessageProperty context; if (ContextMessageProperty.TryGet(putResponse.Message, out context)) { } The if() always returns true and the context is null..... -Jeremy
Free Windows Admin Tool Kit Click here and download it now
April 3rd, 2010 7:30am

u want to disable context manager first, before making the initial put... e.g. that's my code for RST() i would argue that should be done on all clients... while u can extract the InstanceID just by doing some XML magic, my experience told me that if u want to send a message with the ContextMessageProperty in the header, just adding the xml doesn't work... public Message RequestSecurityToken(Message request) { ISecurityTokenService channel = base.ChannelFactory.CreateChannel(); IContextManager contextManger = ((IClientChannel)channel).GetProperty<IContextManager>(); contextManger.Enabled = false; using (channel as IDisposable) { return channel.RequestSecurityToken(request); } }
April 3rd, 2010 9:04am

OK, But I see the Context on the request from the PasswordProxy as well. Are you saying that I do or do not need to use the context for the initial Put when making the RST to the STS Endpoint? If no context is required on the initial call to the STS, then how does the STS know which user we are requesting a token for? -Jeremy
Free Windows Admin Tool Kit Click here and download it now
April 3rd, 2010 10:21pm

Got it. Disabled the contextmanager. Got a context back from the Put. On to the STS..... -J
April 3rd, 2010 10:39pm

do me a flavor, disable the context manager on all channels. on only in the Put()...
Free Windows Admin Tool Kit Click here and download it now
April 3rd, 2010 10:51pm

OK, The STS issued me a challenge. How do I interpret this challenge and package up the response(s)? The online doco for this is totaly wrong. -Jeremy
April 5th, 2010 12:08am

suppose u have public class WorkflowAuthenticationChallenge { [XmlElement()] public byte[] settings; [XmlElement()] public byte[] data; [XmlElement()] public byte[] hash; [XmlElement()] public string Name; [XmlElement()] public Guid ActivityGuid; } Then the Guid/Name tells u what type of challenge it is (e.g. password gate / QA gate) then System.Text.UnicodeEncoding.Unicode.GetString(response.data or response.settings) will give u the string u need... then parse that...
Free Windows Admin Tool Kit Click here and download it now
April 5th, 2010 12:13am

Yep. Just figured out that it is base-64 encoded. So getting the challenges should be straightforward. I see that the response looks like this: 2^߯;f†¦º1èv<€eÚÇCR/äùœ&)PÈõñ4 ª¬vL) Øú2F8jc gA›³ºl@\[ÚnKèÊ`6?‡8½Z/2uºˆ6SrÊ—îùÑÞ¡ÀxЪ!ÿBw So that means that I answered ?'s 2, 4, and 6. I assume I need to use the hash from the challenge when creating the response. What hashing function are you guys expecting? Thanks! -Jeremy
April 5th, 2010 12:19am

sha256 :) Hint: what's the termination char of a string in C++ ?
Free Windows Admin Tool Kit Click here and download it now
April 5th, 2010 12:21am

Also, Seeing as these are hashed - do I need to UCASE them or LCASE them to match the hashes that are stored in the FIM DB? -J
April 6th, 2010 8:00pm

Opps, proposed urs as answer by mistake.. trim white space and convert all to lower case... The client does a bit more to normalize the string... i believe it also removes accents (don't remember exact details)The FIM Password Reset Blog http://blogs.technet.com/aho/
Free Windows Admin Tool Kit Click here and download it now
April 6th, 2010 9:00pm

Trim all white space or just the leading and trailing whitespace? so if I answer " This is My Answer " Should I hash "this is my answer" or "thisismyanswer" Also, I am having trouble getting my hashes to look like the hashes I am seeing in the proxy response. The hashes in the proxy response are 64 bytes. My hashes are 32 bytes(which seems to be correct based on the spec for sha256). I am doing: UTF8Encoding encoder = new UTF8Encoding(); SHA256Managed sha256hasher = new SHA256Managed(); byte[] hashedDataBytes = sha256hasher.ComputeHash(encoder(answer+salt)); hasedAnswer = System.Text.UnicodeEncoding.UTF8.GetString(hasedDataBytes); This assumes that the answer and the salt are strings. I converted the hash in the challege to a string (the salt) using: byte[] encodedHash = Convert.FromBase64String(_QAHashEncoded);return System.Text.UnicodeEncoding.Unicode.GetString(encodedHash); I realize I don't really need to convert the salt to a string and back but that's what I am doing. I don't think that's what is causing my issue though. Are you sure you are using sha256 and not sha512? -Jeremy
April 6th, 2010 9:27pm

Ok, I think I figured out the 64vs32 thing: hasedAnswer = System.Text.UnicodeEncoding.UTF8.GetString(hasedDataBytes); should be: hasedAnswer = System.Text.UnicodeEncoding.Unicode.GetString(hasedDataBytes); Your help on the whitespace question will be appreciated. Thanks! -Jeremy
Free Windows Admin Tool Kit Click here and download it now
April 6th, 2010 9:46pm

trim all.. e.g. private string Normalize(string answer) { return answer.Replace(" ", "").ToLowerInvariant(); } and it's SHA256 private byte[] Hash(byte[] buffer) { HashAlgorithm hashAlgorithm = HashAlgorithm.Create("SHA256"); return hashAlgorithm.ComputeHash(buffer); } make sure u are using utf16, that's what windows uses protected byte[] StringToBytes(string str) { return System.Text.UnicodeEncoding.Unicode.GetBytes(str); } // normalize the ansewr ans = this.Normalize(ans); // append \0 at the end ans = ans + "\0"; // find the hash and add it to the response this.Hash(this.StringToBytes(ans)) u want <id>\n<hashed answer>\n<id>\n<hashed answer>\n<id>\n<hashed answer>\n<id>\n<hashed answer>\n (don't forget the ending \n)The FIM Password Reset Blog http://blogs.technet.com/aho/
April 6th, 2010 11:53pm

Ok, I think I figured out the 64vs32 thing: hasedAnswer = System.Text.UnicodeEncoding.UTF8.GetString(hasedDataBytes); should be: hasedAnswer = System.Text.UnicodeEncoding.Unicode.GetString(hasedDataBytes); Your help on the whitespace question will be appreciated. Thanks! -Jeremy also, i want to point out that it's not possible to turn any arbitary byte[] into a string. You shouldn't do that... One alternative approach is to declare a byte array and only work with that.. e.g. List<byte> result = new ... foreach (IndexAnswerPair) { result.AddRange(this.StringToBytes(current.Index.ToString())) result.AddRange(this.StringToBytes("\n")) result.AddRange(this.Hash(this.StringToBytes( this.Hash( this.Normalize(current.Answer) + "\0" ) ))) result.AddRange(this.StringToBytes("\n")) }The FIM Password Reset Blog http://blogs.technet.com/aho/
Free Windows Admin Tool Kit Click here and download it now
April 7th, 2010 12:01am

OK. I am a bit confused by this: // find the hash and add it to the responsethis.Hash(this.StringToBytes(ans)) and this: private byte[] Hash(byte[] buffer) { HashAlgorithm hashAlgorithm = HashAlgorithm.Create("SHA256"); return hashAlgorithm.ComputeHash(buffer); } If this is your code, then where are you using the <hash>VALUE</hash> that was returned to you in the WorkflowAuthenticationChallenge? I would expect this to be used in your Hash function as a salt: this.Hash(this.StringToBytes(ans)+VALUE); -Jeremy
April 7th, 2010 1:01am

I just did some more testing. My response looks good now. It looks like there is no salt used on the hashes used in the Response. In that case, what is the purpose of the <hash>VALUE</hash> that is present in the WorkflowAuthenticationChallenge? How is the response protected from a dictionary attack against the hashes? -Jeremy
Free Windows Admin Tool Kit Click here and download it now
April 7th, 2010 1:40am

the server will take whatever response it receives, salt it, then rehashes it with SHA256... finally store that in the DB. Also, i want to point out that the message should be encrypted by WCF. WCF tracing happens in the WCF layer so u get the trace in clear text. Remember u need to be admin to enable tracing. And admin attack isn't something we can do much about The FIM Password Reset Blog http://blogs.technet.com/aho/
April 7th, 2010 2:48am

So what is the purpose of the <hash>VALUE</hash> value that is sent to the user in the WorkflowAuthenticationChallenge? -Jeremy
Free Windows Admin Tool Kit Click here and download it now
April 7th, 2010 7:57am

it's not used
April 7th, 2010 12:05pm

OK, Thanks. I am trying to figure out how you were able to get the RequestedeSecurityToken object added to your custom object for the RSTR. When I add a Microsoft.IdentityModel.Protocols.WsTrust.RequestedSecurityToken object to my custom RSTR object, the RSTR object is no longer serializaeable because the RequestedSecurityToken object has no default constructor (). Frankly, I am very frustrated that we cannot use the built-in WSTrust objects to interact with the FIM STS. All of the objects and Actions we are using against the STS are built into Microsoft.IdentityModel.WSTrust. The roadblock I ran into there was when the STS responded with the AuthenticationChallenge, the WSTrus.RSTR could no longer be deserialized. It threw an unknown element exception or something regarding the AuthenticationChallenge. Alternately, I would expect the FIM team to include the objects that we need to use to represent the RST and RSTR objects in the SDK for FIM. As it is, I have 10 or more custom objects I have added to the sample client just to be able to serialize and deserialize objects that theoretically should be supported by the WS-Trust model and frameworks that are being developed and promoted by Microsoft. I really do appreciate all of the help you have given me in getting this far. I am simply frustrated that the existing frameworks and SDK's do not provide the infrastructure we need to sove this problem. -Jeremy
Free Windows Admin Tool Kit Click here and download it now
April 7th, 2010 8:29pm

Alternately, I would expect the FIM team to include the objects that we need to use to represent the RST and RSTR objects in the SDK for FIM. That's not entirely true.. look under Microsoft.ResourceManagement.WebServices.WSTrust namespace in Microsoft.ResourceManagement.dll. There are public classes (i didn't mention anything about supportability though) When Joe first started this project, he wanted to prove that one can write a WS client from scratch, without any product dependency. That's why u see all those custom classes defined in the client. Some of those are public in MS.RM.dll
April 7th, 2010 10:09pm

Correct. I seem them now. I have posted to the Sample Client thread about the direction to go from here. Thanks again for the ongoing support. -Jeremy
Free Windows Admin Tool Kit Click here and download it now
April 8th, 2010 12:20am

OK, Changes to the Sample client to support Password Reset have been posted to codeplex. A summary of the changes requred are as follows: http://fim2010client.codeplex.com/Thread/View.aspx?ThreadId=208916 They are (posted here to maintain the details in this thread: To summarize the changes to the client to support the above functionality: 1 - I fleshed out the implementation of the alternateEndpoint client and added one to the default client 2 - I added an stsEndpoint client to the solution and added one to the default client 3 - I modified the Put methods for the default client to support ContextualSecurityToken objects and ContextMessageProperty parameters 4 - I modified the Put method so it can handle a useAlternateEndpoint parameter - this is used to tell the Default Client to use the Alternate endpoint 5 - I modified the behavior of the endpoint channels so that automatic context management is disabled 6 - I modified the Put function so that the putResponse is provided as an out parameter - this is necessary to be able to examine the response before the call to HandleFault is made. 7 - I modified the Put function so that if an AuthenticationRequiredFault is returned, we can gather the context of that response and then make a call to HandleAuthenticationFault 8 - HandleAuthenticationFault will start a conversation with the STS and attempt to get a security Token for the customer. The only kind of authentication we understand right now is a QAGate 9 - If a QAGate is detected, we will call a delegate to ask QA questions. If no delegate is registered, we will throw an exception. 10 - I have included a sample QAGateQuestionAsker. This can be registered as a delegate to the Default Client to handle asking questions. 11 - The QAGateQuestionAsker uses events every time it wants to ask a question. 12 - I have included a sample PasswordResetTesting console app. This app makes a simple call to the Default Client for ResetPassword. It also includes a few functions that handle the events from the QAGateQuestionAsker and will prompt the user for Challenge/Response questions on the console. 13 - Finally, there is a new method in the Default Client called reset password. This will send a Put to the Alternate Endpoint to initiate the Password Reset function There is a final step to this process: If there is an ActiveDirectoryPasswordReset activity in the Action Phase of the password reset mpr (as is the case in the default install) then an additioanl information required fault is issued. Form there, we need to Put the new password to the endpoint found in this fault. I have not gone to this step because my current scenario does not include having the user provide the new password. I will add this over the next few weeks as time allows. Enjoy! -Jeremy
April 12th, 2010 4:53am

Finally, Major thanks to Anthony Ho for all of his help and support in getthing this working. Without his help, I would still be at least a week away from a working solution. -Jeremy
Free Windows Admin Tool Kit Click here and download it now
April 12th, 2010 5:00am

all these are just design suggestions: u might or might not like this >>6 - I modified the Put function so that the putResponse is provided as an out parameter - this is necessary to be able to examine the response before the call to HandleFault is made. all u really need is the ContextId right? one other approach is to add the ContextId to the AuthenticationRequiredException in the HandleFault function. The imagine u and i are both consuming the custom client, we will both need the same code to extract the ContextId out. The client can provide that functionality >>9 - If a QAGate is detected, we will call a delegate to ask QA questions. If no delegate is registered, we will throw an exception. The design should allow custom gate developer to add the implementation easily.. sorry, i can't look at the code
April 12th, 2010 6:33am

while implementing the code.. ContextualSecurityToken objects and ContextMessageProperty parameters These parameters are not identified..no class defination.. how can we get them.. ??
Free Windows Admin Tool Kit Click here and download it now
June 22nd, 2010 3:34pm

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics