summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/specs/draft-hardt-oauth-01.htm2313
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/TestDirectResponseMessageWithHttpStatus.cs12
-rw-r--r--src/DotNetOpenAuth.sln1
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.csproj53
-rw-r--r--src/DotNetOpenAuth/Messaging/IHttpDirectResponse.cs10
-rw-r--r--src/DotNetOpenAuth/Messaging/IHttpDirectResponseContract.cs43
-rw-r--r--src/DotNetOpenAuth/Messaging/TimespanSecondsEncoder.cs (renamed from src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/TimespanSecondsEncoder.cs)8
-rw-r--r--src/DotNetOpenAuth/OAuth/Protocol.cs2
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/AuthorizationServerDescription.cs64
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapChannel.cs52
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapMessageFactory.cs99
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/ClientBase.cs54
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/IClientTokenManager.cs43
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionFailedResponse.cs21
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionRequest.cs65
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionSuccessResponse.cs40
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/ClientAccountAndPassword/ClientAccountUsernamePasswordFailedResponse.cs22
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/ClientAccountAndPassword/ClientAccountUsernamePasswordRequest.cs69
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/ClientAccountAndPassword/ClientAccountUsernamePasswordSuccessResponse.cs47
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/IMessageWithClientState.cs13
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/MessageBase.cs205
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/RefreshAccessTokenFailedResponse.cs25
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/RefreshAccessTokenRequest.cs57
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/RefreshAccessTokenSuccessResponse.cs44
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppAccessTokenFailedResponse.cs21
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppAccessTokenRequest.cs61
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppAccessTokenSuccessResponse.cs45
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppRequest.cs68
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppResponse.cs60
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/UnauthorizedResponse.cs47
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordCaptchaResponse.cs54
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordFailedResponse.cs22
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordRequest.cs93
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordSuccessResponse.cs51
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordVerificationResponse.cs55
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppAccessTokenBadClientResponse.cs22
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppAccessTokenFailedResponse.cs56
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppAccessTokenRequest.cs90
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppAccessTokenSuccessResponse.cs45
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppFailedResponse.cs47
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppRequest.cs80
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppSuccessResponse.cs49
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/OAuthWrapStrings.Designer.cs72
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/OAuthWrapStrings.resx123
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/Protocol.cs188
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/WebAppClient.cs107
-rw-r--r--src/DotNetOpenAuth/OAuthWrap/WrapUtilities.cs34
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/DirectErrorResponse.cs8
48 files changed, 4852 insertions, 8 deletions
diff --git a/doc/specs/draft-hardt-oauth-01.htm b/doc/specs/draft-hardt-oauth-01.htm
new file mode 100644
index 0000000..e13cdf0
--- /dev/null
+++ b/doc/specs/draft-hardt-oauth-01.htm
@@ -0,0 +1,2313 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!-- saved from url=(0137)https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor34 -->
+<HTML><HEAD><META http-equiv="Content-Type" content="text/html; charset=UTF-8"></HEAD><BODY>
+
+
+
+
+
+
+
+<DIV>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<TABLE summary="layout" width="66%" border="0" cellpadding="0" cellspacing="0"><TBODY><TR><TD><TABLE summary="layout" width="100%" border="0" cellpadding="2" cellspacing="1">
+<TBODY><TR><TD>Internet Engineering Task Force</TD><TD>D. Hardt, Ed.</TD></TR>
+<TR><TD>Internet-Draft</TD><TD>Microsoft</TD></TR>
+<TR><TD>Intended status: Informational</TD><TD>A. Tom</TD></TR>
+<TR><TD>Expires: July 19, 2010</TD><TD>Yahoo!</TD></TR>
+<TR><TD>&nbsp;</TD><TD>B. Eaton</TD></TR>
+<TR><TD>&nbsp;</TD><TD>Google</TD></TR>
+<TR><TD>&nbsp;</TD><TD>Y. Goland</TD></TR>
+<TR><TD>&nbsp;</TD><TD>Microsoft</TD></TR>
+<TR><TD>&nbsp;</TD><TD>January 15, 2010</TD></TR>
+</TBODY></TABLE></TD></TR></TBODY></TABLE>
+<H1><BR>OAuth Web Resource Authorization
+ Profiles<BR>draft-hardt-oauth-01</H1>
+
+<H3>Abstract</H3>
+
+<P>The OAuth Web Resource Authorization Profiles (OAuth WRAP) allow a
+ server hosting a Protected Resource to delegate authorization to one or
+ more authorities. An application (Client) accesses the Protected
+ Resource by presenting a short lived, opaque, bearer token (Access
+ Token) obtained from an authority (Authorization Server). There are
+ Profiles for how a Client may obtain an Access Token when acting
+ autonomously or on behalf of a User.
+</P>
+<H3>Status of this Memo</H3>
+<P>
+This Internet-Draft is submitted to IETF in full
+conformance with the provisions of BCP&nbsp;78 and BCP&nbsp;79.</P>
+<P>
+Internet-Drafts are working documents of the Internet Engineering
+Task Force (IETF), its areas, and its working groups.
+Note that other groups may also distribute working documents as
+Internet-Drafts.</P>
+<P>
+Internet-Drafts are draft documents valid for a maximum of six months
+and may be updated, replaced, or obsoleted by other documents at any time.
+It is inappropriate to use Internet-Drafts as reference material or to cite
+them other than as “work in progress.”</P>
+<P>
+The list of current Internet-Drafts can be accessed at
+<A href="http://www.ietf.org/ietf/1id-abstracts.txt" target="_blank">http://www.ietf.org/ietf/1id-<WBR>abstracts.txt</A>.</P>
+<P>
+The list of Internet-Draft Shadow Directories can be accessed at
+<A href="http://www.ietf.org/shadow.html" target="_blank">http://www.ietf.org/shadow.<WBR>html</A>.</P>
+<P>
+This Internet-Draft will expire on July 19, 2010.</P>
+
+<H3>Copyright Notice</H3>
+<P>
+Copyright (c) 2010 IETF Trust and the persons identified as the
+document authors. All rights reserved.</P>
+<P>
+This document is subject to BCP 78 and the IETF Trust's Legal
+Provisions Relating to IETF Documents in effect on the date of
+publication of this document (<A href="http://trustee.ietf.org/license-info" target="_blank">http://trustee.ietf.org/<WBR>license-info</A>).
+Please review these documents carefully, as they describe your
+rights and restrictions with respect to this document.</P>
+<A name="0.2_toc"></A><BR><HR>
+<H3>Table of Contents</H3>
+<P>
+<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor1">1.</A>&nbsp;
+Overview<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor2">1.1.</A>&nbsp;
+Accessing a Protected Resource<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor3">1.2.</A>&nbsp;
+Autonomous Client Profiles<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor4">1.3.</A>&nbsp;
+User Delegation Profiles<BR>
+<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor5">2.</A>&nbsp;
+Requirements Language<BR>
+<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor6">3.</A>&nbsp;
+Definitions<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor7">3.1.</A>&nbsp;
+URLs<BR>
+<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_ProtectedResource">4.</A>&nbsp;
+Accessing a Protected Resource<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor8">4.1.</A>&nbsp;
+Access Token<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor9">4.2.</A>&nbsp;
+Acquiring an Access Token<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor10">4.3.</A>&nbsp;
+Client Calls Protected Resource Using HTTP Header<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor11">4.4.</A>&nbsp;
+Client Calls Protected Resource Using URL Query Parameter<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor12">4.5.</A>&nbsp;
+Client Calls Protected Resource Using Post Parameter<BR>
+<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_autonomous.profiles">5.</A>&nbsp;
+Acquiring an Access Token: Autonomous Client Profiles<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p1">5.1.</A>&nbsp;
+Client Account and Password Profile<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor13">5.1.1.</A>&nbsp;
+Provisioning<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p1request">5.1.2.</A>&nbsp;
+Client Requests Access Token<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor14">5.1.3.</A>&nbsp;
+Successful Access Token Response from Authorization Server<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor15">5.1.4.</A>&nbsp;
+Unsuccessful Access Token Response from Authorization Server<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor16">5.1.5.</A>&nbsp;
+Client Refreshes Access Token<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p2">5.2.</A>&nbsp;
+Assertion Profile<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor17">5.2.1.</A>&nbsp;
+Provisioning<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p2.assertion">5.2.2.</A>&nbsp;
+Client Obtains Assertion<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p2.request">5.2.3.</A>&nbsp;
+Client Requests Access Token<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor18">5.2.4.</A>&nbsp;
+Successful Access Token Response from Authorization Server<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor19">5.2.5.</A>&nbsp;
+Unsuccessful Access Token Response from Authorization Server<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor20">5.2.6.</A>&nbsp;
+Client Refreshes Access Token<BR>
+<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_user.profiles">6.</A>&nbsp;
+Acquiring an Access Token: User Delegation Profiles<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p3">6.1.</A>&nbsp;
+Username and Password Profile<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor21">6.1.1.</A>&nbsp;
+Provisioning<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p3.password">6.1.2.</A>&nbsp;
+Client Obtains Username and Password<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p3.request">6.1.3.</A>&nbsp;
+Client Requests Access Token<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor22">6.1.4.</A>&nbsp;
+Successful Access Token Response from Authorization Server<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor23">6.1.5.</A>&nbsp;
+Unsuccessful Access Token Response from Authorization Server<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor24">6.1.6.</A>&nbsp;
+Verification URL Response from Authorization Server<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor25">6.1.7.</A>&nbsp;
+CAPTCHA Response from Authorization Server<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor26">6.1.8.</A>&nbsp;
+Client Refreshes Access Token<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor27">6.1.9.</A>&nbsp;
+Successful Access Token Refresh<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor28">6.1.10.</A>&nbsp;
+Unsuccessful Access Token Refresh<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p4">6.2.</A>&nbsp;
+Web App Profile<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor29">6.2.1.</A>&nbsp;
+Provisioning<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p4.authorization">6.2.2.</A>&nbsp;
+Client Directs the User to the Authorization Server<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor30">6.2.3.</A>&nbsp;
+Authorization Server Confirms Authorization Request with User<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor31">6.2.4.</A>&nbsp;
+Authorization Server Directs User back to the Client<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p4.request">6.2.5.</A>&nbsp;
+Client Requests Access Token<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor32">6.2.6.</A>&nbsp;
+Successful Access Token Response from Authorization Server<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor33">6.2.7.</A>&nbsp;
+Unsuccessful Access Token Response from Authorization Server<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="./draft-hardt-oauth-01_files/draft-hardt-oauth-01.htm">6.2.8.</A>&nbsp;
+Client Refreshes Access Token<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor35">6.2.9.</A>&nbsp;
+Successful Access Token Refresh<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor36">6.2.10.</A>&nbsp;
+Unsuccessful Access Token Refresh<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p5">6.3.</A>&nbsp;
+Rich App Profile<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor37">6.3.1.</A>&nbsp;
+Provisioning<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p5.authorization">6.3.2.</A>&nbsp;
+Client Directs the User to the Authorization Server<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor38">6.3.3.</A>&nbsp;
+Authorization Server Confirms Authorization Request with User<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p5.request">6.3.4.</A>&nbsp;
+Client Requests Access Token<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p5.verification">6.3.5.</A>&nbsp;
+Successful Access Token Response from Authorization Server<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor41">6.3.6.</A>&nbsp;
+Unsuccessful Access Token Response from Authorization Server<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor42">6.3.7.</A>&nbsp;
+Client Refreshes Access Token<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor43">6.3.8.</A>&nbsp;
+Successful Access Token Refresh<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor44">6.3.9.</A>&nbsp;
+Unsuccessful Access Token Refresh<BR>
+<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_ParamCon">7.</A>&nbsp;
+Parameter Considerations<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor45">7.1.</A>&nbsp;
+Authorization Server Request / Response Parameter Encoding<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor46">7.2.</A>&nbsp;
+Parameter Size<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor47">7.3.</A>&nbsp;
+Access Token Format<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor48">7.4.</A>&nbsp;
+Refresh Token Format<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor49">7.5.</A>&nbsp;
+Additional Authorization Server Parameters<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor50">7.6.</A>&nbsp;
+Parameter Names and Order<BR>
+<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_IANA">8.</A>&nbsp;
+IANA Considerations<BR>
+<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_Security">9.</A>&nbsp;
+Security Considerations<BR>
+<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_rfc.references1">10.</A>&nbsp;
+References<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_rfc.references1">10.1.</A>&nbsp;
+Normative References<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_rfc.references2">10.2.</A>&nbsp;
+Informative References<BR>
+<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor53">Appendix&nbsp;A.</A>&nbsp;
+Client Account and Password Profile Example<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor54">A.1.</A>&nbsp;
+Provisioning<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor55">A.2.</A>&nbsp;
+Client Requests Access Token<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor56">A.3.</A>&nbsp;
+Successful Access Token Response from Authorization Server<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor57">A.4.</A>&nbsp;
+Client Calls Protected Resource<BR>
+<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor58">Appendix&nbsp;B.</A>&nbsp;
+Web App Profile Example<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor59">B.1.</A>&nbsp;
+Provisioning<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor60">B.2.</A>&nbsp;
+Client Directs the User to the Server<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor61">B.3.</A>&nbsp;
+Authorization Server Confirms Delegation Request with User<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor62">B.4.</A>&nbsp;
+Server Directs User back to the Client<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor63">B.5.</A>&nbsp;
+Client Requests Access Token<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor64">B.6.</A>&nbsp;
+Successful Access Token Response from Authorization Server<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor65">B.7.</A>&nbsp;
+Client Calls Protected Resource<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_anchor66">B.8.</A>&nbsp;
+Client Refreshes Access Token<BR>
+<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_rfc.authors">§</A>&nbsp;
+Authors' Addresses<BR>
+</P>
+<BR clear="all">
+
+<A name="0.2_anchor1"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.1"></A><H3>1.&nbsp;
+Overview</H3>
+
+<P>As the internet has evolved, there is a growing trend for a variety
+ of applications (Clients) to access resources through an API over HTTP
+ or other protocols. Often these resources require authorization for
+ access and are Protected Resources. The systems that are trusted to make
+ authorization decisions may be independent from the Protected Resources
+ for scale and security reasons. The OAuth Web Resource Authorization
+ Profiles (OAuth WRAP) enable a Protected Resource to delegate the
+ authorization to access a Protected Resource to one or more trusted
+ authorities.
+</P>
+<P>Clients that wish to access a Protected Resource first obtain
+ authorization from a trusted authority (Authorization Server). Different
+ credentials and profiles can be used to obtain this authorization, but
+ once authorized, the Client is provided an Access Token, and possible a
+ Refresh Token to obtain new Access Tokens. The Authorization Server
+ typically includes authorization information in the Access Token and
+ digitally signs the Access Token. Protected Resource can verify that an
+ Access Token received from a Client was issued by a trusted
+ Authorization Server and is valid. The Protected Resource can then
+ examine the contents of the Access Token to determine the authorization
+ that has been granted to the Client.
+</P>
+<A name="0.2_anchor2"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.1.1"></A><H3>1.1.&nbsp;
+Accessing a Protected Resource</H3>
+
+<P>The Access Token is opaque to the Client, and can be any format
+ agreed to between the Authorization Server and the Protected Resource
+ enabling existing systems to reuse suitable tokens, or use a standard
+ token format such as a Simple Web Token or JSON Web Token. Since the
+ Access Token provides the Client authorization to the Protected
+ Resource for the life of the Access Token, the Authorization Server
+ should issue Access Tokens that expire within an appropriate time.
+ When an Access Token expires, the Client requests a new Access Token
+ from the Authorization Server, which once again computes the Client's
+ authorization, and issues a new Access Token. <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_fig1">Figure&nbsp;1</A> below shows the flow between the Client and
+ Authorization Server (A,B); and then between the Client and Protected
+ Resource (C,D):
+</P><BR><HR>
+<A name="0.2_fig1"></A>
+<DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> +---+ +---------------+
+ | C |--(A)------ credentials ---------&gt;| Authorization |
+ | l |&lt;-(B)------ Access Token ---------| Server |
+ | i | +---------------+
+ | e |
+ | n | Access Token +-----------+
+ | t |--(C)----- in HTTP header -------&gt;| Protected |
+ | |&lt;-(D)------ API response ---------| Resource |
+ +---+ +-----------+
+</PRE></DIV><TABLE border="0" cellpadding="0" cellspacing="2" align="center"><TBODY><TR><TD align="center"><FONT face="monaco, MS Sans Serif" size="1"><B>&nbsp;Figure&nbsp;1&nbsp;</B></FONT><BR></TD></TR></TBODY></TABLE><HR>
+
+<P>In step A, the Client presents credentials to the Authorization
+ Server in exchange for an Access Token.
+</P>
+<P> A Profile specifies the credentials to be provided in step A, and
+ how the Client obtains them. This specification defines a number of
+ Profiles; additional Profiles may be defined to support additional
+ scenarios. The Profiles in this specification are separated into two
+ groups: autonomous profiles where the Client as acting for itself, and
+ user delegation profiles where the Client is acting on behalf of a
+ User.
+</P>
+<A name="0.2_anchor3"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.1.2"></A><H3>1.2.&nbsp;
+Autonomous Client Profiles</H3>
+
+<P>The following two Profiles (see <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_autonomous.profiles">Section&nbsp;5<SPAN> (</SPAN><SPAN>Acquiring an Access Token: Autonomous Client Profiles</SPAN><SPAN>)</SPAN></A>) are recommended for scenarios
+ involving a Client acting autonomously.
+</P>
+<P>Client Account and Password Profile (<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p1">Section&nbsp;5.1<SPAN> (</SPAN><SPAN>Client Account and Password Profile</SPAN><SPAN>)</SPAN></A>): This
+ is the simplest Profile. The Client is provisioned with an account name
+ and corresponding password by the Authorization Server. The Client
+ presents the account name and password to the Access Token URL at the
+ Authorization Server in exchange for an Access Token. This Profile is
+ not intended for a Client acting on behalf of a User. See the User
+ Delegation Profiles.
+</P>
+<P>Assertion Profile (<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p2">Section&nbsp;5.2<SPAN> (</SPAN><SPAN>Assertion Profile</SPAN><SPAN>)</SPAN></A>): This profile enables a
+ Client with a <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_OASIS.saml-core-2.0-os">SAML<SPAN> (</SPAN><SPAN>Cantor, S., Kemp, J., Philpott, R., and E. Maler, “Assertions and Protocol for the OASIS Security Assertion Markup Language (SAML) V2.0,” March&nbsp;2005.</SPAN><SPAN>)</SPAN></A> [OASIS.saml‑core‑2.0‑os] or other
+ assertion recognized by the Authorization Server. The Client presents
+ the assertion to the Access Token URL at the Authorization Server in
+ exchange for an Access Token. How the Client obtains the assertion is
+ out of scope of OAuth WRAP.
+</P>
+<P>Access Tokens are short lived bearer tokens. When the Protected
+ Resource is presented with an expired Access Token by the Client, the
+ Protected Resource returns an error. The Client presents the assertion
+ once again to the Authorization Server to obtain a new Access
+ Token.
+</P>
+<A name="0.2_anchor4"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.1.3"></A><H3>1.3.&nbsp;
+User Delegation Profiles</H3>
+
+<P>Common scenarios involve the User delegating to a Client to act on
+ the User's behalf, adding another party (the User) to the protocol. In
+ these Profiles (see <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_user.profiles">Section&nbsp;6<SPAN> (</SPAN><SPAN>Acquiring an Access Token: User Delegation Profiles</SPAN><SPAN>)</SPAN></A>), the Client
+ receives a Refresh Token when it acquires the first Access Token. When
+ an Access Token expires, the Client presents the Refresh Token to
+ acquire a new Access Token. Refresh Tokens are sensitive as they
+ represent long-lived permissions to access a Protected Resource and
+ are always transmitted using HTTPS.
+</P>
+<P>Username and Password Profile (<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p3">Section&nbsp;6.1<SPAN> (</SPAN><SPAN>Username and Password Profile</SPAN><SPAN>)</SPAN></A>): While
+ the User may use a username and password to authenticate to the
+ Authorization Server, it is undesirable for the Client to store the
+ User's username and password. In this profile the User provides their
+ username and password to an application (Client) they have installed
+ on their device. The Client presents a Client Identifier, the username
+ and password (credentials) to the Access Token URL at the
+ Authorization Server in exchange for an Access Token and a Refresh
+ Token as depicted in <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_fig2">Figure&nbsp;2</A> below.
+</P><BR><HR>
+<A name="0.2_fig2"></A>
+<DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> +---+ +---------------+
+ | C |--(A)------ credentials ---------&gt;| Authorization |
+ | l |&lt;-(B)------ Access Token ---------| Server |
+ | i | Refresh Token +---------------+
+ | e |
+ | n | Access Token +-----------+
+ | t |--(C)----- in HTTP header -------&gt;| Protected |
+ | |&lt;-(D)------ API response ---------| Resource |
+ +---+ +-----------+
+
+</PRE></DIV><TABLE border="0" cellpadding="0" cellspacing="2" align="center"><TBODY><TR><TD align="center"><FONT face="monaco, MS Sans Serif" size="1"><B>&nbsp;Figure&nbsp;2&nbsp;</B></FONT><BR></TD></TR></TBODY></TABLE><HR>
+
+<P>When the Access Token expires, the Client presents the Refresh
+ Token to the Refresh Token URL at the Authorization Server in exchange
+ for a new Access Token (<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_fig3">Figure&nbsp;3</A>, steps A and B).
+ The Client then uses the new Access Token to access the Protected
+ Resource (<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_fig3">Figure&nbsp;3</A>, steps C and D).
+</P><BR><HR>
+<A name="0.2_fig3"></A>
+<DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> +---+ +---------------+
+ | C |--(A)----- Refresh Token --------&gt;| Authorization |
+ | l |&lt;-(B)------ Access Token ---------| Server |
+ | i | +---------------+
+ | e |
+ | n | Access Token +-----------+
+ | t |--(C)----- in HTTP header -------&gt;| Protected |
+ | |&lt;-(D)------ API response ---------| Resource |
+ +---+ +-----------+
+
+</PRE></DIV><TABLE border="0" cellpadding="0" cellspacing="2" align="center"><TBODY><TR><TD align="center"><FONT face="monaco, MS Sans Serif" size="1"><B>&nbsp;Figure&nbsp;3&nbsp;</B></FONT><BR></TD></TR></TBODY></TABLE><HR>
+
+<P>Web App Profile (<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p4">Section&nbsp;6.2<SPAN> (</SPAN><SPAN>Web App Profile</SPAN><SPAN>)</SPAN></A>): It is undesirable for
+ a User to provide their Authorization Server username and password to
+ web applications. Additionally, the User may authenticate to the
+ Authorization Server using other mechanisms than a username and
+ password. In this profile, a web application (Client) has been
+ provisioned with a Client Identifier and Client Secret and may have
+ registered a Callback URL. <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_fig4">Figure&nbsp;4</A> below
+ illustrates the protocol. (A) The Client initiates the protocol by
+ redirecting the User to the User Authorization URL at the
+ Authorization Server passing the Client Identifier and the Callback
+ URL. (B) The Authorization Server authenticates the User, confirms the
+ User would like to authorize the Client to access the Protected
+ Resource, and generates a Verification Code. (C) The Authorization
+ Server then redirects the User to the Callback URL at the Client
+ passing along the Verification Code.
+</P><BR><HR>
+<A name="0.2_fig4"></A>
+<DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> +---------+
+ | Web App |
+ | Client |
+ +---------+
+ v ^
+ | |
+ (A) (C)
+ | |
+ \ \
+ +---------+ +---------------+
+ | |\---(C)-- Verification Code ----&lt;| |
+ | User | | Authorization |
+ | at |&lt;---(B)-- User authenticates ---&gt;| Server |
+ | Browser | | |
+ | |\---(A)-- Client Identifier ----&gt;| |
+ +---------+ +---------------+
+</PRE></DIV><TABLE border="0" cellpadding="0" cellspacing="2" align="center"><TBODY><TR><TD align="center"><FONT face="monaco, MS Sans Serif" size="1"><B>&nbsp;Figure&nbsp;4&nbsp;</B></FONT><BR></TD></TR></TBODY></TABLE><HR>
+
+<P>Similar to step A in <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_fig2">Figure&nbsp;2</A>, the Client then
+ presents the Client Identifier, Client Secret, Callback URL and
+ Verification code (credentials) to the Access Token URL at the
+ Authorization Server for an Access Token and a Refresh Token.
+</P>
+<P>Rich App Profile (<A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p5">Section&nbsp;6.3<SPAN> (</SPAN><SPAN>Rich App Profile</SPAN><SPAN>)</SPAN></A>): This profile is
+ suitable when the Client is an application the User has installed on
+ their device and a web browser is available, but it is undesirable for
+ the User to provide their username and password to an application, or
+ the user may not be using a username and password to authenticate to
+ the Authorization Server.
+</P>
+<P>The Client initiates the protocol by directing the User's browser
+ to the Authorization URL at the Authorization Server passing the
+ Client Identifier and potentially a Callback URL. The Authorization
+ Server authenticates the User, confirms the User would like to
+ authorize the Client to access the Protected Resource, and generates a
+ Verification Code. The Verification Code may be communicated back to
+ the Client in a number of ways:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>a.</DT>
+<DD>the Authorization Server presents the Verification Code to the
+ User, who is instructed to enter the Verification Code directly in
+ the Client;
+</DD>
+<DT>b.</DT>
+<DD>the Client reads the Verification Code from the title of the
+ web page presented by the Authorization Server;
+</DD>
+<DT>c.</DT>
+<DD>the Authorization Server redirects the User to the Callback URL
+ that presents Client specific language for the User to enter the
+ Verification Code into the Client; or
+</DD>
+<DT>d.</DT>
+<DD>the Client has registered a custom scheme and the Authorization
+ Server redirects the browser to the custom scheme that causes the
+ User's browser to load the Client application with the
+ Verification Code as a parameter.
+</DD>
+</DL></BLOCKQUOTE>
+
+<P>Similar to step A in <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_fig2">Figure&nbsp;2</A>, the Client then
+ presents the Client Identifier, Callback URL (if provided) and
+ Verification code (credentials) to the Access Token URL at the
+ Authorization Server for an Access Token and a Refresh Token.
+</P>
+<A name="0.2_anchor5"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.2"></A><H3>2.&nbsp;
+Requirements Language</H3>
+
+<P>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_RFC2119">[RFC2119]<SPAN> (</SPAN><SPAN>Bradner, S., “Key words for use in RFCs to Indicate Requirement Levels,” March&nbsp;1997.</SPAN><SPAN>)</SPAN></A>. Domain name examples use <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_RFC2606">[RFC2606]<SPAN> (</SPAN><SPAN>Eastlake, D. and A. Panitz, “Reserved Top Level DNS Names,” June&nbsp;1999.</SPAN><SPAN>)</SPAN></A>.
+</P>
+<A name="0.2_anchor6"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.3"></A><H3>3.&nbsp;
+Definitions</H3>
+
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>Access Token:</DT>
+<DD>a short lived bearer token issued by the
+ Authorization Server to the Client. The Access Token is presented by
+ the Client to the Protected Resource to access protected
+ resources.
+</DD>
+<DT>Authorization Server:</DT>
+<DD>an authorization resource that
+ issues Access Tokens to Clients after successful authorization. May
+ be the same entity as the Protected Resource.
+</DD>
+<DT>Client:</DT>
+<DD>an application that would like access to a
+ Protected Resource. Client Identifier:"&gt; a value used by a Client
+ to identify itself to the Authorization Server. This may be a human
+ readable string or an opaque identifier.
+</DD>
+<DT>Client Secret:</DT>
+<DD>a secret used by a web application
+ Client to establish ownership of the Client Identifier.
+</DD>
+<DT>Profile:</DT>
+<DD>a mechanism for a Client to obtain an Access
+ Token from an Authorization Server.
+</DD>
+<DT>Protected Resource:</DT>
+<DD>a protected API that allows access
+ via OAuth WRAP. May be the same entity as the Authorization Server.
+ Refresh Token:"&gt; a long lived bearer token used by a Client to
+ acquire an Access Token from an Authorization Server.
+</DD>
+<DT>User:</DT>
+<DD>an individual who has an account with the
+ Authorization Server.
+</DD>
+<DT>Verification Code:</DT>
+<DD>a code used by a Client to verify
+ the User has authorized the Client to have specific access to a
+ Protected Resource.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_anchor7"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.3.1"></A><H3>3.1.&nbsp;
+URLs</H3>
+
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>Access Token URL:</DT>
+<DD>the Authorization Server URL at
+ which an Access Token is requested by the Client. The URL may
+ accept a variety of parameters depending on the Profile. A Refresh
+ Token may also be returned to the Client. This URL MUST be an
+ HTTPS URL and MUST always be called with POST.
+</DD>
+<DT>Callback URL:</DT>
+<DD>the Client URL where the User will be
+ redirected after an authorization request to the Authorization
+ Server.
+</DD>
+<DT>Refresh Token URL:</DT>
+<DD>the Authorization Server URL at
+ which a Refresh Token is presented in exchange for a new Access
+ Token is requested. This URL MUST be an HTTPS URL and MUST always
+ be called with POST.
+</DD>
+<DT>User Authorization URL:</DT>
+<DD>the Authorization Server URL
+ where the Client redirects the User to make an authorization
+ request.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_ProtectedResource"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.4"></A><H3>4.&nbsp;
+Accessing a Protected Resource</H3>
+
+<P>Clients always present an Access Token to access a Protected
+ Resource. Use of the Authorization header is RECOMMENDED, since HTTP
+ implementations are aware that Authorization headers have special
+ security properties and may require special treatment in caches and
+ logs. Protected Resources SHOULD take precautions to insure that Access
+ Tokens are not inadvertently logged or captured. In addition to the
+ methods presented here, the Protected Resource MAY allow the Client to
+ present the Access Token using any scheme agreed on by the Client and
+ Protected Resource.
+</P>
+<A name="0.2_anchor8"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.4.1"></A><H3>4.1.&nbsp;
+Access Token</H3>
+
+<P>The exact format of the Access Token is opaque to Clients and is
+ out of scope of this specification. However, Protected Resources MUST
+ be able to verify that the Access Token was issued by a trusted
+ Authorization Server and is still valid. Access Tokens SHOULD
+ periodically expire. The expiry time of Access Tokens is determined as
+ an appropriate balance between excessive resource utilization if too
+ short and unauthorized access if too long.
+</P>
+<A name="0.2_anchor9"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.4.2"></A><H3>4.2.&nbsp;
+Acquiring an Access Token</H3>
+
+<P>An Authorization Server may support one or more protocol profiles
+ that enable a Client to obtain an Access Token that can be used to
+ access a Protected Resource.
+</P>
+<P>Client developers only need to implement the profile(s) that align
+ with how their application will be deployed and are supported by the
+ Authorization Server.
+</P>
+<P>Authorization Server developers only need to implement the
+ profile(s) that are appropriate for them.
+</P>
+<P>Protected Resource developers do not implement a profile as the
+ Client always interacts with the Protected Resource by presenting an
+ Access Token.
+</P>
+<P><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_ParamCon">Section&nbsp;7<SPAN> (</SPAN><SPAN>Parameter Considerations</SPAN><SPAN>)</SPAN></A> has general information about
+ parameters passed to and from the Authorization Server.
+</P>
+<P>See <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_autonomous.profiles">Section&nbsp;5<SPAN> (</SPAN><SPAN>Acquiring an Access Token: Autonomous Client Profiles</SPAN><SPAN>)</SPAN></A> for how the Client
+ acquires an Access Token when acting autonomously, and <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_user.profiles">Section&nbsp;6<SPAN> (</SPAN><SPAN>Acquiring an Access Token: User Delegation Profiles</SPAN><SPAN>)</SPAN></A> for how the Client acquires an Access
+ Token when acting acting on behalf of a User.
+</P>
+<A name="0.2_anchor10"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.4.3"></A><H3>4.3.&nbsp;
+Client Calls Protected Resource Using HTTP Header</H3>
+
+<P>The Protected Resource SHOULD enable Clients to access the
+ Protected Resource by including the Access Token in the HTTP
+ Authorization header using the OAuth WRAP scheme with the following
+ parameter:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>access_token</DT>
+<DD> REQUIRED. The value of the
+ Access Token
+</DD>
+</DL></BLOCKQUOTE>
+
+<P>For example, if the Access Token is the string 123456789, the HTTP
+ header would be:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> Authorization: WRAP access_token="123456789"
+</PRE></DIV>
+<P>Note that per section 1.2 of <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_RFC2617">[RFC2617]<SPAN> (</SPAN><SPAN>Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S., Leach, P., Luotonen, A., and L. Stewart, “HTTP Authentication: Basic and Digest Access Authentication,” June&nbsp;1999.</SPAN><SPAN>)</SPAN></A> that
+ the following header is also valid:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> Authorization: WRAP access_token = 123456789
+</PRE></DIV>
+<P>If the Access Token has expired or is invalid, the Protected
+ Resource MUST return:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 401 Unauthorized
+</PRE></DIV>
+<P>and the HTTP header:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> WWW-Authenticate: WRAP
+</PRE></DIV>
+<A name="0.2_anchor11"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.4.4"></A><H3>4.4.&nbsp;
+Client Calls Protected Resource Using URL Query Parameter</H3>
+
+<P>The Protected Resource MAY allow the Client to access protected
+ resources at the Protected Resource by including the following HTTP
+ URL query parameter in the URL:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>access_token</DT>
+<DD> REQUIRED. The value of the
+ Access Token
+</DD>
+</DL></BLOCKQUOTE>
+
+<P>If the Access Token has expired or is invalid, the Protected
+ Resource MUST return:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 401 Unauthorized
+</PRE></DIV>
+<P>and the HTTP header:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> WWW-Authenticate: WRAP
+</PRE></DIV>
+<A name="0.2_anchor12"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.4.5"></A><H3>4.5.&nbsp;
+Client Calls Protected Resource Using Post Parameter</H3>
+
+<P>The Protected Resource MAY allow the Client to access protected
+ resources at the Protected Resource by including the following
+ parameter in the body of a HTTP post message formatted as
+ application/x-www-form-<WBR>urlencoded per <A href="http://www.w3.org/TR/1999/REC-W3C.REC-html40-19980424-19991224/interact/forms.html#h-17.13.4.1" target="_blank">17.13.4</A>
+ of <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_W3C.REC-html40-19980424">HTML 4.01<SPAN> (</SPAN><SPAN>Hors, A., Jacobs, I., and D. Raggett, “HTML 4.0 Specification,” April&nbsp;1998.</SPAN><SPAN>)</SPAN></A> [W3C.REC‑html40‑19980424]:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>access_token</DT>
+<DD> REQUIRED. The value of the
+ Access Token
+</DD>
+</DL></BLOCKQUOTE>
+
+<P>If the Access Token has expired or is invalid, the Protected
+ Resource MUST return:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 401 Unauthorized
+</PRE></DIV>
+<P>and the HTTP header:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> WWW-Authenticate: WRAP
+</PRE></DIV>
+<A name="0.2_autonomous.profiles"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.5"></A><H3>5.&nbsp;
+Acquiring an Access Token: Autonomous Client Profiles</H3>
+
+<P>These are the profiles the Client uses when acting autonomously.
+</P>
+<A name="0.2_p1"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.5.1"></A><H3>5.1.&nbsp;
+Client Account and Password Profile</H3>
+
+<P>This profile is suitable when the Client is an application calling
+ the Protected Resource on behalf of an organization and the
+ Authorization Server accepts account passwords for authentication.
+ This enables the Authorization Server to use an existing
+ authentication mechanism. This profile SHOULD NOT be used when the
+ Client is acting on behalf of a user. Profiles <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p3">6.1<SPAN> (</SPAN><SPAN>Username and Password Profile</SPAN><SPAN>)</SPAN></A>, <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p4">6.2<SPAN> (</SPAN><SPAN>Web App Profile</SPAN><SPAN>)</SPAN></A> or
+ <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p5">6.3<SPAN> (</SPAN><SPAN>Rich App Profile</SPAN><SPAN>)</SPAN></A> are RECOMMENDED when a
+ Client is acting on behalf of a User.
+</P>
+<A name="0.2_anchor13"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.5.1.1"></A><H3>5.1.1.&nbsp;
+Provisioning</H3>
+
+<P>Prior to initiating this protocol profile, the Client MUST have
+ obtained an account name and account password from the Authorization
+ Server.
+</P>
+<A name="0.2_p1request"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.5.1.2"></A><H3>5.1.2.&nbsp;
+Client Requests Access Token</H3>
+
+<P>The Client makes an HTTPS request to the Authorization Server's
+ Access Token URL using POST. The request contains the following
+ parameters:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_name</DT>
+<DD> REQUIRED. The account
+ name.
+</DD>
+<DT>wrap_password</DT>
+<DD> REQUIRED. The account
+ password.
+</DD>
+<DT>wrap_scope</DT>
+<DD> OPTIONAL. The Authorization
+ Server MAY define authorization scope values for the Client to
+ include.
+</DD>
+<DT>Additional parameters</DT>
+<DD>Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_anchor14"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.5.1.3"></A><H3>5.1.3.&nbsp;
+Successful Access Token Response from Authorization Server</H3>
+
+<P>If successful, the Authorization Server returns:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 200 OK
+</PRE></DIV>
+<P>with the Refresh Token and an Access Token in the response body.
+ The response body contains the following parameters:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_refresh_token</DT>
+<DD> REQUIRED. The
+ Refresh Token.
+</DD>
+<DT>wrap_access_token</DT>
+<DD> REQUIRED. The Access
+ Token.
+</DD>
+<DT>wrap_access_token_expires_in</DT>
+<DD> OPTIONAL.
+ The lifetime of the Access Token in seconds. For example, 3600
+ represents one hour.
+</DD>
+<DT>Additional parameters</DT>
+<DD> Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<P>The Client may now use the Access Token to access the Protected
+ Resource per <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_ProtectedResource">Section&nbsp;4<SPAN> (</SPAN><SPAN>Accessing a Protected Resource</SPAN><SPAN>)</SPAN></A>
+</P>
+<A name="0.2_anchor15"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.5.1.4"></A><H3>5.1.4.&nbsp;
+Unsuccessful Access Token Response from Authorization Server</H3>
+
+<P>If the Client account name and password are invalid, the
+ Authorization Server MUST respond with:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 401 Unauthorized
+</PRE></DIV>
+<P>and the HTTP header:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> WWW-Authenticate: WRAP
+</PRE></DIV>
+<P>The Client MUST obtain a valid account name and password before
+ retrying the request.
+</P>
+<A name="0.2_anchor16"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.5.1.5"></A><H3>5.1.5.&nbsp;
+Client Refreshes Access Token</H3>
+
+<P>Authorization Servers SHOULD issue Access Tokens that expire and
+ require Clients to refresh them. Upon receiving the HTTP 401
+ response when accessing protected resources per <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_ProtectedResource">Section&nbsp;4<SPAN> (</SPAN><SPAN>Accessing a Protected Resource</SPAN><SPAN>)</SPAN></A>, the Client should request a new
+ Access Token by repeating <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p1request">Section&nbsp;5.1.2<SPAN> (</SPAN><SPAN>Client Requests Access Token</SPAN><SPAN>)</SPAN></A>
+</P>
+<A name="0.2_p2"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.5.2"></A><H3>5.2.&nbsp;
+Assertion Profile</H3>
+
+<A name="0.2_anchor17"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.5.2.1"></A><H3>5.2.1.&nbsp;
+Provisioning</H3>
+
+<P>Prior to initiating this protocol profile, the Client MUST have a
+ mechanism for obtained an assertion from an assertion issuer that
+ can be presented to the Authorization Server for access to the
+ Protected Resource.
+</P>
+<A name="0.2_p2.assertion"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.5.2.2"></A><H3>5.2.2.&nbsp;
+Client Obtains Assertion</H3>
+
+<P>The Client obtains an assertion. The process for obtaining the
+ assertion is defined by the assertion issuer and the Authorization
+ Server, and is out of scope of this specification.
+</P>
+<A name="0.2_p2.request"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.5.2.3"></A><H3>5.2.3.&nbsp;
+Client Requests Access Token</H3>
+
+<P>The Client makes an HTTPS request to the Authorization Server's
+ Access Token URL using POST. The request contains the following
+ parameters:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_assertion_format</DT>
+<DD> REQUIRED. The
+ format of the assertion as defined by the Authorization
+ Server.
+</DD>
+<DT>wrap_assertion</DT>
+<DD> REQUIRED. The
+ assertion.
+</DD>
+<DT>wrap_scope</DT>
+<DD> OPTIONAL. The Authorization
+ Server MAY define authorization scope values for the Client to
+ include
+</DD>
+<DT>Additional parameters</DT>
+<DD> Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_anchor18"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.5.2.4"></A><H3>5.2.4.&nbsp;
+Successful Access Token Response from Authorization Server</H3>
+
+<P>If successful, the Authorization Server returns:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 200 OK
+</PRE></DIV>
+<P>with the Access Token in the response body. The response body
+ contains the following parameters:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_access_token</DT>
+<DD> REQUIRED. The Access
+ Token.
+</DD>
+<DT>wrap_access_token_expires_in</DT>
+<DD> OPTIONAL.
+ The lifetime of the Access Token in seconds. For example, 3600
+ represents one hour.
+</DD>
+<DT>Additional parameters</DT>
+<DD> Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<P>The Client may now use the Access Token to access the Protected
+ Resource per <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_ProtectedResource">Section&nbsp;4<SPAN> (</SPAN><SPAN>Accessing a Protected Resource</SPAN><SPAN>)</SPAN></A>.
+</P>
+<A name="0.2_anchor19"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.5.2.5"></A><H3>5.2.5.&nbsp;
+Unsuccessful Access Token Response from Authorization Server</H3>
+
+<P>If the assertion is not valid, the Authorization Server MUST
+ respond with:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 401 Unauthorized
+</PRE></DIV>
+<P>and the HTTP header:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> WWW-Authenticate: WRAP
+</PRE></DIV>
+<P>The Client MUST obtain a valid assertion by repeating <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p2.assertion">Section&nbsp;5.2.2<SPAN> (</SPAN><SPAN>Client Obtains Assertion</SPAN><SPAN>)</SPAN></A> before retrying the request.
+</P>
+<A name="0.2_anchor20"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.5.2.6"></A><H3>5.2.6.&nbsp;
+Client Refreshes Access Token</H3>
+
+<P>Authorization Servers SHOULD issue Access Tokens that expire and
+ require Clients to refresh them. Upon receiving the HTTP 401
+ response when accessing protected resources per <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_ProtectedResource">Section&nbsp;4<SPAN> (</SPAN><SPAN>Accessing a Protected Resource</SPAN><SPAN>)</SPAN></A>, the Client should request a new
+ Access Token by repeating <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p2.request">Section&nbsp;5.2.3<SPAN> (</SPAN><SPAN>Client Requests Access Token</SPAN><SPAN>)</SPAN></A> if the
+ assertion is still valid, otherwise the Client MUST obtain a new,
+ valid assertion by repeating <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p2.assertion">Section&nbsp;5.2.2<SPAN> (</SPAN><SPAN>Client Obtains Assertion</SPAN><SPAN>)</SPAN></A>.
+</P>
+<A name="0.2_user.profiles"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6"></A><H3>6.&nbsp;
+Acquiring an Access Token: User Delegation Profiles</H3>
+
+<P>These are the profiles the Client uses when acting on behalf of a
+ User.
+</P>
+<A name="0.2_p3"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.1"></A><H3>6.1.&nbsp;
+Username and Password Profile</H3>
+
+<P>This profile is suitable where the Client is an application the
+ User has installed on their computer and the User uses a username and
+ password to authenticate to the Authorization Server. This profile
+ enables a Client to act on behalf of the User without having to
+ permanently store the User's username and password.
+</P>
+<A name="0.2_anchor21"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.1.1"></A><H3>6.1.1.&nbsp;
+Provisioning</H3>
+
+<P>Prior to initiating this protocol profile, the Authorization
+ Server MAY have required the Client to have obtained a Client
+ Identifier from the Authorization Server.
+</P>
+<A name="0.2_p3.password"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.1.2"></A><H3>6.1.2.&nbsp;
+Client Obtains Username and Password</H3>
+
+<P>The Client obtains the User's username and password from the
+ user. The Client MUST discard the username and password once an
+ Access Token has been obtained.
+</P>
+<A name="0.2_p3.request"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.1.3"></A><H3>6.1.3.&nbsp;
+Client Requests Access Token</H3>
+
+<P>The Client makes an HTTPS request to the Authorization Server's
+ Access Token URL using POST. The request contains the following
+ parameters:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_client_id</DT>
+<DD> REQUIRED. The Client
+ Identifier.
+</DD>
+<DT>wrap_username</DT>
+<DD> REQUIRED. The User's
+ username.
+</DD>
+<DT>wrap_password</DT>
+<DD> REQUIRED. The User's
+ password.
+</DD>
+<DT>wrap_scope</DT>
+<DD> OPTIONAL. The Authorization
+ Server MAY define authorization scope values for the Client to
+ include.
+</DD>
+<DT>Additional parameters</DT>
+<DD> Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_anchor22"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.1.4"></A><H3>6.1.4.&nbsp;
+Successful Access Token Response from Authorization Server</H3>
+
+<P>If successful, the Authorization Server returns:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 200 OK
+</PRE></DIV>
+<P>with the Access Token in the response body. The response body
+ contains the following parameters:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_access_token</DT>
+<DD> REQUIRED. The Access
+ Token.
+</DD>
+<DT>wrap_access_token_expires_in</DT>
+<DD> OPTIONAL.
+ The lifetime of the Access Token in seconds. For example, 3600
+ represents one hour.
+</DD>
+<DT>Additional parameters</DT>
+<DD> Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<P>The Client MUST discard the User's username and password. The
+ Client securely stores the Refresh Token for later use. The Client
+ may now use the Access Token to access the Protected Resource per
+ <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_ProtectedResource">Section&nbsp;4<SPAN> (</SPAN><SPAN>Accessing a Protected Resource</SPAN><SPAN>)</SPAN></A>.
+</P>
+<A name="0.2_anchor23"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.1.5"></A><H3>6.1.5.&nbsp;
+Unsuccessful Access Token Response from Authorization Server</H3>
+
+<P>The Authorization Server MUST verify User's username and
+ password. If the verification fails, the Authorization Server MUST
+ respond with:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 401 Unauthorized
+</PRE></DIV>
+<P>and the HTTP header:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> WWW-Authenticate: WRAP
+</PRE></DIV>
+<P>The Client needs to obtain a valid username and password from the
+ User per <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p3.password">Section&nbsp;6.1.2<SPAN> (</SPAN><SPAN>Client Obtains Username and Password</SPAN><SPAN>)</SPAN></A> before retrying the
+ request.
+</P>
+<A name="0.2_anchor24"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.1.6"></A><H3>6.1.6.&nbsp;
+Verification URL Response from Authorization Server</H3>
+
+<P>If the Authorization Server determines that the Client may be
+ malicious, the Authorization Server MAY require the Client to
+ instruct the User to visit a Verification URL. The Authorization
+ Server communicates its requirement by responding to the Client's
+ Access Token request with the following:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 400 Bad Request
+</PRE></DIV>
+<P>and the body of the Authorization Server response contains the
+ following parameter:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_verification_url</DT>
+<DD>REQUIRED. The
+ verification URL that the Client MUST either load in the User's
+ browser, or display for the User to enter into a browser.
+</DD>
+</DL></BLOCKQUOTE>
+
+<P>The Client MUST then wait for the User to indicate they have
+ successfully completed the verification process at the Authorization
+ Server and attempt to obtain an Access Token Refresh Token per <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p3.request">Section&nbsp;6.1.3<SPAN> (</SPAN><SPAN>Client Requests Access Token</SPAN><SPAN>)</SPAN></A> again.
+</P>
+<A name="0.2_anchor25"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.1.7"></A><H3>6.1.7.&nbsp;
+CAPTCHA Response from Authorization Server</H3>
+
+<P>If the Authorization Server determines that the Client may be
+ malicious, the Authorization Server MAY require the Client to have
+ the User solve a CAPTCHA Puzzle. The Authorization Server
+ communicates its requirement by responding to the Client's Access
+ Token request with the following:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 400 Bad Request
+</PRE></DIV>
+<P>and the body of the Authorization Server response contains the
+ following parameter:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_captcha_url</DT>
+<DD>REQUIRED. The URL to
+ the CAPTCHA puzzle image.
+</DD>
+</DL></BLOCKQUOTE>
+
+<P>The Client MUST present the User with the CAPTCHA puzzle and
+ prompt for a solution. The Client then MAY attempt to obtain an
+ Access Token per <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p3.request">Section&nbsp;6.1.3<SPAN> (</SPAN><SPAN>Client Requests Access Token</SPAN><SPAN>)</SPAN></A> again, including
+ the following additional parameter:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_captcha_url</DT>
+<DD>REQUIRED. The URL to
+ the CAPTCHA puzzle received from the Authorization Server.
+</DD>
+<DT>wrap_captcha_solution</DT>
+<DD>REQUIRED. The
+ solution string to the CAPTCHA puzzle as defined by the
+ Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_anchor26"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.1.8"></A><H3>6.1.8.&nbsp;
+Client Refreshes Access Token</H3>
+
+<P>Refreshing an Access Token is the same in <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p3">Section&nbsp;6.1<SPAN> (</SPAN><SPAN>Username and Password Profile</SPAN><SPAN>)</SPAN></A>, <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p4">Section&nbsp;6.2<SPAN> (</SPAN><SPAN>Web App Profile</SPAN><SPAN>)</SPAN></A>, and <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p5">Section&nbsp;6.3<SPAN> (</SPAN><SPAN>Rich App Profile</SPAN><SPAN>)</SPAN></A>. Authorization Servers SHOULD issue Access
+ Tokens that expire and require Clients to refresh them. Upon
+ receiving the HTTP 401 response when accessing protected resources
+ per <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_ProtectedResource">Section&nbsp;4<SPAN> (</SPAN><SPAN>Accessing a Protected Resource</SPAN><SPAN>)</SPAN></A>, the Client makes an
+ HTTPS request to the Authorization Server's Refresh Token URL using
+ POST. The request contains the following parameters:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_refresh_token</DT>
+<DD>REQUIRED. The Refresh
+ Token that was received in <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p3.request">Section&nbsp;6.1.3<SPAN> (</SPAN><SPAN>Client Requests Access Token</SPAN><SPAN>)</SPAN></A>
+</DD>
+<DT>Additional parameters:</DT>
+<DD>Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_anchor27"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.1.9"></A><H3>6.1.9.&nbsp;
+Successful Access Token Refresh</H3>
+
+<P>If successful, the Authorization Server returns:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 200 OK
+</PRE></DIV>
+<P>with the Access Token in the response body. The response body
+ contains the following parameters:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_access_token</DT>
+<DD> REQUIRED. The Access
+ Token.
+</DD>
+<DT>wrap_access_token_expires_in</DT>
+<DD> OPTIONAL.
+ The lifetime of the Access Token in seconds. For example, 3600
+ represents one hour.
+</DD>
+<DT>Additional parameters</DT>
+<DD> Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_anchor28"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.1.10"></A><H3>6.1.10.&nbsp;
+Unsuccessful Access Token Refresh</H3>
+
+<P>The Authorization Server MUST verify the Refresh Token. If the
+ verification fails, the Authorization Server MUST respond with
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 401 Unauthorized
+</PRE></DIV>
+<P>and the HTTP header:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> WWW-Authenticate: WRAP
+</PRE></DIV>
+<P>The Client MUST again request authorization from the User by
+ prompting for the User's username and password per <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p3.password">Section&nbsp;6.1.2<SPAN> (</SPAN><SPAN>Client Obtains Username and Password</SPAN><SPAN>)</SPAN></A> before retrying the request.
+</P>
+<A name="0.2_p4"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.2"></A><H3>6.2.&nbsp;
+Web App Profile</H3>
+
+<P>This profile is suitable when the Client is a web application
+ calling the Protected Resource on behalf of a User. This profile
+ enables a Client to act on behalf of the User without acquiring a
+ User's credentials.
+</P>
+<A name="0.2_anchor29"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.2.1"></A><H3>6.2.1.&nbsp;
+Provisioning</H3>
+
+<P>Prior to initiating this protocol profile, the Client MUST have
+ obtained a Client Identifier and Client Secret from the
+ Authorization Server. The Authorization Server MAY have also
+ required the Client to register the Callback URL.
+</P>
+<A name="0.2_p4.authorization"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.2.2"></A><H3>6.2.2.&nbsp;
+Client Directs the User to the Authorization Server</H3>
+
+<P>The Client initiates an authorization request by redirecting the
+ User's browser to the Authorization Server's User Authorization URL,
+ with the following parameters:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_client_id</DT>
+<DD> REQUIRED. The Client
+ Identifier.
+</DD>
+<DT>wrap_callback </DT>
+<DD> REQUIRED. The
+ Callback URL. An absolute URL to which the Authorization Server
+ will redirect the User back after the User has approved the
+ authorization request. Authorization Servers MAY require that
+ the wrap_callback URL match the previously registered value for
+ the Client Identifier.
+</DD>
+<DT>wrap_client_state</DT>
+<DD>OPTIONAL. An opaque
+ value that Clients can use to maintain state associated with
+ this request. If this value is present, the Authorization Server
+ MUST return it to the Client's Callback URL.
+</DD>
+<DT>wrap_scope</DT>
+<DD> OPTIONAL. The Authorization
+ Server MAY define authorization scope values for the Client to
+ include.
+</DD>
+<DT>Additional parameters</DT>
+<DD> Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_anchor30"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.2.3"></A><H3>6.2.3.&nbsp;
+Authorization Server Confirms Authorization Request with User</H3>
+
+<P>Upon receiving an authorization request from the Client by a
+ redirection of the User's browser, the Authorization Server
+ authenticates the user, presents the User with the Protected
+ Resource access that will be granted to the Client, and prompts the
+ User to confirm the request.
+</P>
+<P>If the User denies the request, the Authorization Server MAY
+ allow the User to return to the Client Callback URL with the
+ following parameters added:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_error_reason</DT>
+<DD> REQUIRED. Value is
+ user_denied
+</DD>
+<DT>wrap_client_state</DT>
+<DD> REQUIRED if the
+ Client sent the value in the authorization request in <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p4.authorization">Section&nbsp;6.2.2<SPAN> (</SPAN><SPAN>Client Directs the User to the Authorization Server</SPAN><SPAN>)</SPAN></A>
+</DD>
+</DL></BLOCKQUOTE>
+
+<P>If the User approves the request, the Authorization Server
+ generates a Verification Code and associates it with the Client
+ Identifier and Callback URL.
+</P>
+<A name="0.2_anchor31"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.2.4"></A><H3>6.2.4.&nbsp;
+Authorization Server Directs User back to the Client</H3>
+
+<P>If the User approved the request, the Authorization Server MUST
+ redirect the User back to the Callback URL, with the following
+ parameters added:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_verification_code</DT>
+<DD> REQUIRED. The
+ Verification Code.
+</DD>
+<DT>wrap_client_state</DT>
+<DD> REQUIRED if the
+ Client sent the value in the authorization request in <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p4.authorization">Section&nbsp;6.2.2<SPAN> (</SPAN><SPAN>Client Directs the User to the Authorization Server</SPAN><SPAN>)</SPAN></A>
+</DD>
+<DT>Additional parameters:</DT>
+<DD>Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_p4.request"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.2.5"></A><H3>6.2.5.&nbsp;
+Client Requests Access Token</H3>
+
+<P>The Client makes an HTTPS request to the Authorization Server's
+ Access Token URL, using POST. The request contains the following
+ parameters in the body of the request:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_client_id</DT>
+<DD> REQUIRED. The Client
+ Identifier
+</DD>
+<DT>wrap_client_secret</DT>
+<DD>REQUIRED. The Client
+ Secret
+</DD>
+<DT>wrap_verification_code</DT>
+<DD> REQUIRED. The
+ Verification Code.
+</DD>
+<DT>wrap_callback</DT>
+<DD> REQUIRED. The Callback
+ URL used to obtain the Verification Code.
+</DD>
+<DT>Additional parameters:</DT>
+<DD>Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_anchor32"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.2.6"></A><H3>6.2.6.&nbsp;
+Successful Access Token Response from Authorization Server</H3>
+
+<P>After receiving the Access Token request, the Authorization
+ Server verifies the request as follows:
+</P>
+<P></P>
+<BLOCKQUOTE>
+<P>the Client Secret MUST match the Client Identifer
+</P>
+<P>the Client Identifier MUST match the Client Identifier from
+ the authorization redirect
+</P>
+<P>the Verification Code MUST match the Client Identifier from
+ the authorization redirect
+</P>
+<P>the Callback URL MUST match the Callback URL from the
+ authorization redirect
+</P>
+<P>if the Callback URL or Callback URL pattern was registered
+ with the Authorization Server, the Callback URL MUST match the
+ Callback URL or Callback URL pattern as defined by the
+ Authorization Server
+</P>
+<P>the Verification Code MUST not have expired
+</P>
+</BLOCKQUOTE>
+
+<P>The Authorization Server MAY also require that a Verification
+ Code is not reused.
+</P>
+<P>If verification is successful, the Authorization Server
+ returns:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 200 OK
+</PRE></DIV>
+<P>with the Refresh Token and the Access Token in the response body.
+ The response body contains the following parameters:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_refresh_token</DT>
+<DD> REQUIRED. The
+ Refresh Token.
+</DD>
+<DT>wrap_access_token</DT>
+<DD> REQUIRED. The Access
+ Token.
+</DD>
+<DT>wrap_access_token_expires_in</DT>
+<DD> OPTIONAL.
+ The lifetime of the Access Token in seconds. For example, 3600
+ represents one hour.
+</DD>
+<DT>Additional parameters</DT>
+<DD> Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<P>The Client securely stores the Refresh Token for later use. The
+ Client may now use the Access Token to access the Protected Resource
+ per <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_ProtectedResource">Section&nbsp;4<SPAN> (</SPAN><SPAN>Accessing a Protected Resource</SPAN><SPAN>)</SPAN></A>.
+</P>
+<A name="0.2_anchor33"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.2.7"></A><H3>6.2.7.&nbsp;
+Unsuccessful Access Token Response from Authorization Server</H3>
+
+<P>The Authorization Server MUST first verify the Client Identifier
+ and Client Secret. If they are invalid, the Authorization Server
+ MUST respond with:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 401 Unauthorized
+</PRE></DIV>
+<P>and the HTTP header:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> WWW-Authenticate: WRAP
+</PRE></DIV>
+<P>The Client MUST obtain a valid Client Identifier and Client
+ Secret before retrying the request.
+</P>
+<P>The Authorization Server MUST then verify that the Callback URL
+ and Verification Code are associated with the Client Identifier. If
+ the verification fails, the Authorization Server MUST respond
+ with:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 400 Bad Request
+</PRE></DIV>
+<P>and the body of the Authorization Server response contains the
+ following parameters:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_error_reason</DT>
+<DD>OPTIONAL. If all the
+ parameters are valid except that the Verification Code has
+ expired or been revoked, then it is RECOMMENDED that this
+ parameter be included and if so, then the value MUST be:
+</DD>
+<DT>
+<DD><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> expired_verification_code
+</PRE></DIV>
+</DD>
+<DT>
+<DD>This enables the Client to detect it needs a new Verification
+ Code and to direct the User to the Authorization Server per
+ <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p4.authorization">Section&nbsp;6.2.2<SPAN> (</SPAN><SPAN>Client Directs the User to the Authorization Server</SPAN><SPAN>)</SPAN></A>
+</DD>
+<DT>
+<DD>If the Callback URL is invalid, the value MUST be:
+</DD>
+<DT>
+<DD><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> invalid_callback
+</PRE></DIV>
+</DD>
+<DT>Additional parameters</DT>
+<DD> Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_anchor34"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.2.8"></A><H3>6.2.8.&nbsp;
+Client Refreshes Access Token</H3>
+
+<P>Refreshing an Access Token is the same in <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p3">Section&nbsp;6.1<SPAN> (</SPAN><SPAN>Username and Password Profile</SPAN><SPAN>)</SPAN></A>, <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p4">Section&nbsp;6.2<SPAN> (</SPAN><SPAN>Web App Profile</SPAN><SPAN>)</SPAN></A>, and <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p5">Section&nbsp;6.3<SPAN> (</SPAN><SPAN>Rich App Profile</SPAN><SPAN>)</SPAN></A>. Authorization Servers SHOULD issue Access
+ Tokens that expire and require Clients to refresh them. Upon
+ receiving the HTTP 401 response when accessing protected resources
+ per <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_ProtectedResource">Section&nbsp;4<SPAN> (</SPAN><SPAN>Accessing a Protected Resource</SPAN><SPAN>)</SPAN></A>, the Client makes an
+ HTTPS request to the Authorization Server's Refresh Token URL using
+ POST. The request contains the following parameters:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_refresh_token</DT>
+<DD>REQUIRED. The Refresh
+ Token that was received in <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p4.request">Section&nbsp;6.2.5<SPAN> (</SPAN><SPAN>Client Requests Access Token</SPAN><SPAN>)</SPAN></A>
+</DD>
+<DT>Additional parameters:</DT>
+<DD>Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_anchor35"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.2.9"></A><H3>6.2.9.&nbsp;
+Successful Access Token Refresh</H3>
+
+<P>If successful, the Authorization Server returns:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 200 OK
+</PRE></DIV>
+<P>with the Access Token in the response body. The response body
+ contains the following parameters:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_access_token</DT>
+<DD> REQUIRED. The Access
+ Token.
+</DD>
+<DT>wrap_access_token_expires_in</DT>
+<DD> OPTIONAL.
+ The lifetime of the Access Token in seconds. For example, 3600
+ represents one hour.
+</DD>
+<DT>Additional parameters</DT>
+<DD> Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_anchor36"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.2.10"></A><H3>6.2.10.&nbsp;
+Unsuccessful Access Token Refresh</H3>
+
+<P>The Authorization Server MUST verify the Refresh Token. If the
+ verification fails, the Authorization Server MUST respond with
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 401 Unauthorized
+</PRE></DIV>
+<P>and the HTTP header:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> WWW-Authenticate: WRAP
+</PRE></DIV>
+<P>The Client MUST again request authorization from the User per
+ <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p4.authorization">Section&nbsp;6.2.2<SPAN> (</SPAN><SPAN>Client Directs the User to the Authorization Server</SPAN><SPAN>)</SPAN></A>.
+</P>
+<A name="0.2_p5"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.3"></A><H3>6.3.&nbsp;
+Rich App Profile</H3>
+
+<P>This profile is suitable where the Client is an application the
+ User has installed on their computer and there is a browser available
+ for the Client to launch. This profile enables a Client to act on
+ behalf of the User regardless of how the User authenticates to the
+ Server and without access to the User's credentials.
+</P>
+<A name="0.2_anchor37"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.3.1"></A><H3>6.3.1.&nbsp;
+Provisioning</H3>
+
+<P>Prior to initiating this protocol profile, the Client MAY be
+ required to register the Client Identifier and/or the Callback URL
+ with the Server.
+</P>
+<A name="0.2_p5.authorization"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.3.2"></A><H3>6.3.2.&nbsp;
+Client Directs the User to the Authorization Server</H3>
+
+<P>The Client initiates an authorization request by opening the
+ User's browser with the Server's User Authorization URL, and
+ including the following parameters:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_client_id</DT>
+<DD> REQUIRED. The Client
+ Identifier.
+</DD>
+<DT>wrap_callback </DT>
+<DD> OPTIONAL. A Callback
+ URL where the Authorization Server MAY redirect the User's
+ browser after the User responds to the authorization
+ request.
+</DD>
+<DT>wrap_client_state</DT>
+<DD>OPTIONAL. An opaque
+ value that Clients can use to maintain state associated with
+ this request. If this value is present, the Authorization Server
+ MUST return it to the Client's Callback URL.
+</DD>
+<DT>wrap_scope</DT>
+<DD> OPTIONAL. The Authorization
+ Server MAY define authorization scope values for the Client to
+ include.
+</DD>
+<DT>Additional parameters</DT>
+<DD> Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_anchor38"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.3.3"></A><H3>6.3.3.&nbsp;
+Authorization Server Confirms Authorization Request with User</H3>
+
+<P>Upon receiving an authorization request from the Client by way of
+ the User's browser, the Authorization Server authenticates the user,
+ presents the User with the Protected Resource access that will be
+ granted to the Client, and prompts the User to confirm the request.
+ If the User approves the request, the Authorization Server generates
+ a Verification Code. If the User denied access, the Authorization
+ Server MAY set the Verification Code to the reserved value:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> user_denied
+</PRE></DIV>
+<P>It is RECOMMENDED the Verification Code be single use, and expire
+ within minutes of issue. There are a number of mechanisms for the
+ Authorization Server to transmit the Verification Code to the
+ Client, specified below.
+</P>
+<P>Rich Application interaction with the User and the Authorization
+ Server is an area of active research and development. If the Rich
+ Application is able to retrieve the verifier directly from the
+ callback URL returned by the Authorization Server, an improved user
+ experience is possible. However, not all applications are able to
+ interact with the Authorization Server in this manner.
+</P>
+<A name="0.2_anchor39"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.3.3.1"></A><H3>6.3.3.1.&nbsp;
+Applications with Callback URLs</H3>
+
+<P>Rich Applications may be able to receive callback URLs in any
+ of several ways. For example, the Rich Application may register a
+ custom protocol handler with the application platform so that the
+ application will be invoked when the browser is redirected to the
+ callback URL. Alternatively, the callback URL may point to a web
+ site with which the Rich Application has a trust relationship. The
+ web site can then pass the Callback URL down to the Rich
+ Application for processing. Finally, the Callback URL may point to
+ a web site that will display the Callback URL to the screen along
+ with instructions for the user to enter the Verification Code into
+ the application.
+</P>
+<P>For Rich Applications with a Callback URL, the Authorization
+ Server MUST redirect the User back to the Callback URL, with the
+ following parameters added:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_verification_code</DT>
+<DD> REQUIRED. The
+ Verification Code
+</DD>
+<DT>wrap_client_state</DT>
+<DD> REQUIRED if the
+ Client sent the value in the authorization request in <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p5.authorization">Section&nbsp;6.3.2<SPAN> (</SPAN><SPAN>Client Directs the User to the Authorization Server</SPAN><SPAN>)</SPAN></A>
+</DD>
+<DT>Additional parameters</DT>
+<DD> Any
+ additional parameters, as defined by the Authorization
+ Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<P>If the User denied access, the Server MAY redirect the User's
+ browser to the Callback URL with the Verification Code set to the
+ reserved value:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> user_denied
+</PRE></DIV>
+<A name="0.2_anchor40"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.3.3.2"></A><H3>6.3.3.2.&nbsp;
+Applications without Callback URLs</H3>
+
+<P>Rich Applications without Callback URLs need to receive the
+ verification code in other ways. For Rich Applications without a
+ Callback URL, the Authorization Server MUST present the
+ Verification Code on the web page and instruct the user to enter
+ it into the Client.
+</P>
+<P>The Server MAY also append the Verification Code to the title
+ of the HTML page so that Clients that have access to the title of
+ the browser's current page can obtain the Verification Code
+ without requiring the User enter the Verification Code into the
+ Client. The Client can parse the title looking for "code=" and
+ then the rest of the title is the Verification Code. If adding the
+ Verification Code to the title of the HTML page, the Server MUST
+ also include the wrap_client_state parameter if sent from the
+ Client as the "state=" parameter.
+</P>
+<P>Eg. For <A href="http://example.com/" target="_blank">example.com</A> where the Verification Code = WF34F7HG and
+ Client State = NMMGFJJ, the Server would set the title of the page
+ to something like:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> &lt;title&gt;Successful delegation, code=WF34F7HG
+state=NMMGFJJ&lt;/title&gt;</PRE></DIV>
+<P>If the User denied access, the Server MAY append
+ code=user_denied to the title of the HTML page so that the Client
+ can detect that the User has denied access.
+</P>
+<A name="0.2_p5.request"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.3.4"></A><H3>6.3.4.&nbsp;
+Client Requests Access Token</H3>
+
+<P>The Client makes an HTTPS request to the Server's Access Token
+ URL using POST. The request contains the following parameters:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_client_id</DT>
+<DD> REQUIRED. The Client
+ Identifier
+</DD>
+<DT>wrap_verification_code</DT>
+<DD> REQUIRED. The
+ Verification Code.
+</DD>
+<DT>Additional parameters:</DT>
+<DD>Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_p5.verification"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.3.5"></A><H3>6.3.5.&nbsp;
+Successful Access Token Response from Authorization Server</H3>
+
+<P>The Server checks the Verification Code was previously issued to
+ the same Client Identifier, has not expired and has not been used.
+ If these conditions are met, the Server marks the Verification Code
+ as being used and returns:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 200 OK
+</PRE></DIV>
+<P>with the Refresh Token and an Access Token in the response body.
+ The response body contains the following parameters:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_refresh_token</DT>
+<DD> REQUIRED. The
+ Refresh Token.
+</DD>
+<DT>wrap_access_token</DT>
+<DD> REQUIRED. The Access
+ Token.
+</DD>
+<DT>wrap_access_token_expires_in</DT>
+<DD> OPTIONAL.
+ The lifetime of the Access Token in seconds. For example, 3600
+ represents one hour.
+</DD>
+<DT>Additional parameters</DT>
+<DD> Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<P>The Client securely stores the Refresh Token for later use. The
+ Client may now use the Access Token to access the Protected Resource
+ per <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_ProtectedResource">Section&nbsp;4<SPAN> (</SPAN><SPAN>Accessing a Protected Resource</SPAN><SPAN>)</SPAN></A>.
+</P>
+<A name="0.2_anchor41"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.3.6"></A><H3>6.3.6.&nbsp;
+Unsuccessful Access Token Response from Authorization Server</H3>
+
+<P>The Authorization Server MUST first verify the Client Identifier
+ and Client Secret per <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p5.verification">Section&nbsp;6.3.5<SPAN> (</SPAN><SPAN>Successful Access Token Response from Authorization Server</SPAN><SPAN>)</SPAN></A>. If
+ they are invalid, the Authorization Server MUST respond with:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 401 Unauthorized
+</PRE></DIV>
+<P>and the HTTP header:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> WWW-Authenticate: WRAP
+</PRE></DIV>
+<P>The Client needs to obtain a new Verification Code per <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p5.authorization">Section&nbsp;6.3.2<SPAN> (</SPAN><SPAN>Client Directs the User to the Authorization Server</SPAN><SPAN>)</SPAN></A>.
+</P>
+<A name="0.2_anchor42"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.3.7"></A><H3>6.3.7.&nbsp;
+Client Refreshes Access Token</H3>
+
+<P>Refreshing an Access Token is the same in <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p3">Section&nbsp;6.1<SPAN> (</SPAN><SPAN>Username and Password Profile</SPAN><SPAN>)</SPAN></A>, <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p4">Section&nbsp;6.2<SPAN> (</SPAN><SPAN>Web App Profile</SPAN><SPAN>)</SPAN></A>, and <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p5">Section&nbsp;6.3<SPAN> (</SPAN><SPAN>Rich App Profile</SPAN><SPAN>)</SPAN></A>. Authorization Servers SHOULD issue Access
+ Tokens that expire and require Clients to refresh them. Upon
+ receiving the HTTP 401 response when accessing protected resources
+ per <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_ProtectedResource">Section&nbsp;4<SPAN> (</SPAN><SPAN>Accessing a Protected Resource</SPAN><SPAN>)</SPAN></A>, the Client makes an
+ HTTPS request to the Authorization Server's Refresh Token URL using
+ POST. The request contains the following parameters:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_refresh_token</DT>
+<DD>REQUIRED. The Refresh
+ Token that was received in <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p5.request">Section&nbsp;6.3.4<SPAN> (</SPAN><SPAN>Client Requests Access Token</SPAN><SPAN>)</SPAN></A>
+</DD>
+<DT>Additional parameters:</DT>
+<DD>Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_anchor43"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.3.8"></A><H3>6.3.8.&nbsp;
+Successful Access Token Refresh</H3>
+
+<P>If successful, the Authorization Server returns:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 200 OK
+</PRE></DIV>
+<P>with the Access Token in the response body. The response body
+ contains the following parameters:
+</P>
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>wrap_access_token</DT>
+<DD> REQUIRED. The Access
+ Token.
+</DD>
+<DT>wrap_access_token_expires_in</DT>
+<DD> OPTIONAL.
+ The lifetime of the Access Token in seconds. For example, 3600
+ represents one hour.
+</DD>
+<DT>Additional parameters</DT>
+<DD> Any additional
+ parameters, as defined by the Authorization Server.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_anchor44"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.6.3.9"></A><H3>6.3.9.&nbsp;
+Unsuccessful Access Token Refresh</H3>
+
+<P>The Authorization Server MUST verify the Refresh Token. If the
+ verification fails, the Authorization Server MUST respond with
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> HTTP 401 Unauthorized
+</PRE></DIV>
+<P>and the HTTP header:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> WWW-Authenticate: WRAP
+</PRE></DIV>
+<P>The Client MUST again request authorization from the User per
+ <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_p5.authorization">Section&nbsp;6.3.2<SPAN> (</SPAN><SPAN>Client Directs the User to the Authorization Server</SPAN><SPAN>)</SPAN></A>.
+</P>
+<A name="0.2_ParamCon"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.7"></A><H3>7.&nbsp;
+Parameter Considerations</H3>
+
+<A name="0.2_anchor45"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.7.1"></A><H3>7.1.&nbsp;
+Authorization Server Request / Response Parameter Encoding</H3>
+
+<P>All requests made directly to the Authorization Server use the HTTP
+ POST method and the parameters MUST be in the body of the message and
+ formatted as application/x-www-form-<WBR>urlencoded per <A href="http://www.w3.org/TR/1999/REC-W3C.REC-html40-19980424-19991224/interact/forms.html#h-17.13.4.1" target="_blank">17.13.4</A>
+ of <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_W3C.REC-html40-19980424">HTML 4.01<SPAN> (</SPAN><SPAN>Hors, A., Jacobs, I., and D. Raggett, “HTML 4.0 Specification,” April&nbsp;1998.</SPAN><SPAN>)</SPAN></A> [W3C.REC‑html40‑19980424].
+</P>
+<P>Any parameters in the response from the Authorization Server MUST
+ be in the body of the message and formatted as
+ application/x-www-form-<WBR>urlencoded per <A href="http://www.w3.org/TR/1999/REC-W3C.REC-html40-19980424-19991224/interact/forms.html#h-17.13.4.1" target="_blank">17.13.4</A>
+ of <A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_W3C.REC-html40-19980424">HTML 4.01<SPAN> (</SPAN><SPAN>Hors, A., Jacobs, I., and D. Raggett, “HTML 4.0 Specification,” April&nbsp;1998.</SPAN><SPAN>)</SPAN></A> [W3C.REC‑html40‑19980424].
+</P>
+<A name="0.2_anchor46"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.7.2"></A><H3>7.2.&nbsp;
+Parameter Size</H3>
+
+<P></P>
+<BLOCKQUOTE><DL>
+<DT>HTTP Headers</DT>
+<DD> Web servers often impose a
+ maximum on the combined size of all HTTP headers ranging from 8KB
+ to 16KB. The size of the Access Token should be small enough to
+ ensure the total size of the HTTP headers does not exceed the
+ limits of web servers.
+</DD>
+<DT>URLs</DT>
+<DD> Web servers and browsers often
+ impose a maximum on the total length of the URL of as low as 2083
+ bytes. The length of URLs exposed by the Authorization Server and
+ the length of parameters passed on a URL should be minimized so
+ that the total length does not exceed this limit.
+</DD>
+</DL></BLOCKQUOTE>
+
+<A name="0.2_anchor47"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.7.3"></A><H3>7.3.&nbsp;
+Access Token Format</H3>
+
+<P>OAuth WRAP does not specify the format of the Access Token. The
+ format is mutually agreed to by the Authorization Server and the
+ Protected Resource and is opaque to the Client. The Access Token
+ format MUST consist of legal characters in an HTTP header per
+ [Reference needed]
+</P>
+<P>The Simple Web Token (SWT) and JSON Web Token (JWT) are possible
+ Access Token formats.
+</P>
+<P>[TBD: entropy recommendations for Access Token so that it remains
+ secure during its lifetime]
+</P>
+<A name="0.2_anchor48"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.7.4"></A><H3>7.4.&nbsp;
+Refresh Token Format</H3>
+
+<P>OAuth WRAP does not specify the format of the Refresh Token. The
+ Refresh Token is both generated and consumed by the Authorization
+ Server and is opaque to the Client and never exposed to the Protected
+ Resource. The Refresh Token is a long lived credential, and should
+ contain enough entropy that it cannot be guessed. The size limitations
+ of the Access Token are not applicable to the Refresh Token as the
+ Refresh Token is always in the body of an HTTP message.
+</P>
+<A name="0.2_anchor49"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.7.5"></A><H3>7.5.&nbsp;
+Additional Authorization Server Parameters</H3>
+
+<P>The Authorization Server may define additional parameters to be
+ included in are returned from calls to the Access Token URL or User
+ Authorization URL. Parameters that start with wrap_ are reserved and
+ may not be used.
+</P>
+<A name="0.2_anchor50"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.7.6"></A><H3>7.6.&nbsp;
+Parameter Names and Order</H3>
+
+<P>All parameter names are case sensitive. The parameters my appear in
+ any order. Unrecognized parameters are allowed, but MUST be
+ ignored.
+</P>
+<A name="0.2_IANA"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.8"></A><H3>8.&nbsp;
+IANA Considerations</H3>
+
+<P>This memo includes no request to IANA.
+</P>
+<A name="0.2_Security"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.9"></A><H3>9.&nbsp;
+Security Considerations</H3>
+
+<P>TBD: need to put in all the security considerations for
+ implementors.
+</P>
+<A name="0.2_rfc.references"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.10"></A><H3>10.&nbsp;
+References</H3>
+
+<A name="0.2_rfc.references1"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<H3>10.1.&nbsp;Normative References</H3>
+<TABLE width="99%" border="0">
+<TBODY><TR><TD valign="top"><A name="0.2_RFC2119">[RFC2119]</A></TD>
+<TD><A href="mailto:sob@harvard.edu" target="_blank">Bradner, S.</A>, “<A href="http://tools.ietf.org/html/rfc2119" target="_blank">Key words for use in RFCs to Indicate Requirement Levels</A>,” BCP&nbsp;14, RFC&nbsp;2119, March&nbsp;1997 (<A href="ftp://ftp.isi.edu/in-notes/rfc2119.txt" target="_blank">TXT</A>, <A href="http://xml.resource.org/public/rfc/html/rfc2119.html" target="_blank">HTML</A>, <A href="http://xml.resource.org/public/rfc/xml/rfc2119.xml" target="_blank">XML</A>).</TD></TR>
+<TR><TD valign="top"><A name="0.2_RFC2606">[RFC2606]</A></TD>
+<TD><A href="mailto:dee3@us.ibm.com" target="_blank">Eastlake, D.</A> and <A href="mailto:buglady@fuschia.net" target="_blank">A. Panitz</A>, “<A href="http://tools.ietf.org/html/rfc2606" target="_blank">Reserved Top Level DNS Names</A>,” BCP&nbsp;32, RFC&nbsp;2606, June&nbsp;1999 (<A href="ftp://ftp.isi.edu/in-notes/rfc2606.txt" target="_blank">TXT</A>).</TD></TR>
+<TR><TD valign="top"><A name="0.2_RFC2617">[RFC2617]</A></TD>
+<TD><A href="mailto:john@math.nwu.edu" target="_blank">Franks, J.</A>, <A href="mailto:pbaker@verisign.com" target="_blank">Hallam-Baker, P.</A>, <A href="mailto:jeff@AbiSource.com" target="_blank">Hostetler, J.</A>, <A href="mailto:lawrence@agranat.com" target="_blank">Lawrence, S.</A>, <A href="mailto:paulle@microsoft.com" target="_blank">Leach, P.</A>, Luotonen, A., and <A href="mailto:stewart@OpenMarket.com" target="_blank">L. Stewart</A>, “<A href="http://tools.ietf.org/html/rfc2617" target="_blank">HTTP Authentication: Basic and Digest Access Authentication</A>,” RFC&nbsp;2617, June&nbsp;1999 (<A href="ftp://ftp.isi.edu/in-notes/rfc2617.txt" target="_blank">TXT</A>, <A href="http://xml.resource.org/public/rfc/html/rfc2617.html" target="_blank">HTML</A>, <A href="http://xml.resource.org/public/rfc/xml/rfc2617.xml" target="_blank">XML</A>).</TD></TR>
+<TR><TD valign="top"><A name="0.2_W3C.REC-html40-19980424">[W3C.REC-html40-19980424]</A></TD>
+<TD>Hors, A., Jacobs, I., and D. Raggett, “<A href="http://www.w3.org/TR/1998/REC-html40-19980424" target="_blank">HTML 4.0 Specification</A>,” World Wide Web Consortium Recommendation&nbsp;REC-html40-<WBR>19980424, April&nbsp;1998 (<A href="http://www.w3.org/TR/1998/REC-html40-19980424" target="_blank">HTML</A>).</TD></TR>
+</TBODY></TABLE>
+
+<A name="0.2_rfc.references2"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<H3>10.2.&nbsp;Informative References</H3>
+<TABLE width="99%" border="0">
+<TBODY><TR><TD valign="top"><A name="0.2_I-D.narten-iana-considerations-rfc2434bis">[I-D.narten-iana-<WBR>considerations-rfc2434bis]</A></TD>
+<TD>Narten, T. and H. Alvestrand, “<A href="http://www.ietf.org/internet-drafts/draft-narten-iana-considerations-rfc2434bis-09.txt" target="_blank">Guidelines for Writing an IANA Considerations Section in RFCs</A>,” draft-narten-iana-<WBR>considerations-rfc2434bis-09 (work in progress), March&nbsp;2008 (<A href="http://www.ietf.org/internet-drafts/draft-narten-iana-considerations-rfc2434bis-09.txt" target="_blank">TXT</A>).</TD></TR>
+<TR><TD valign="top"><A name="0.2_OASIS.saml-core-2.0-os">[OASIS.saml-core-2.0-os]</A></TD>
+<TD><A href="mailto:cantor.2@osu.edu" target="_blank">Cantor, S.</A>, <A href="mailto:John.Kemp@nokia.com" target="_blank">Kemp, J.</A>, <A href="mailto:rphilpott@rsasecurity.com" target="_blank">Philpott, R.</A>, and <A href="mailto:eve.maler@sun.com" target="_blank">E. Maler</A>, “<A href="http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf" target="_blank">Assertions and Protocol for the OASIS Security Assertion Markup Language
+ (SAML) V2.0</A>,” OASIS Standard&nbsp;saml-core-2.0-os, March&nbsp;2005.</TD></TR>
+<TR><TD valign="top"><A name="0.2_OAuth Core 1.0">[OAuth Core 1.0]</A></TD>
+<TD>Hammer-Lahav, E., “<A href="http://tools.ietf.org/html/draft-hammer-oauth-08" target="_blank">OAuth Core 1.0 Protocol</A>.”</TD></TR>
+</TBODY></TABLE>
+
+<A name="0.2_anchor53"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.A"></A><H3>Appendix A.&nbsp;
+Client Account and Password Profile Example</H3>
+
+<P>In this example, <A href="http://crm.example.com/" target="_blank">crm.example.com</A> is an application server that has a
+ Protected Resource at <A href="https://crm.example.com/data" target="_blank">https://crm.example.com/data</A>. DataDumper is an
+ application acting as a Client that periodically calls
+ <A href="https://crm.example.com/data" target="_blank">https://crm.example.com/data</A>. The Protected Resource trusts the
+ Authorization Server <A href="http://auth.example.net/" target="_blank">auth.example.net</A> to determine if a Client has
+ access.
+</P>
+<A name="0.2_anchor54"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.A.1"></A><H3>A.1.&nbsp;
+Provisioning</H3>
+
+<P>The Authorization Server documentation defines the Access Token URL
+ as:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> <A href="https://auth.example.net/access_token" target="_blank">https://auth.example.net/<WBR>access_token</A>
+</PRE></DIV>
+<P>The Authorization Server has defined that the parameter Audience be
+ included in calls to the Access Token URL.
+</P>
+<P>The Client has been provisioned with the following:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> Client Account: datadumper Client Password: j2hw7GPsl0
+</PRE></DIV>
+<P>The Protected Resource and the Authorization Server have agreed to
+ use a Simple Web Token (SWT) for the Access Token with the reserved
+ attributes Issuer, Audience, ExpiresOn and the public attribute
+ net.example.auth.account and have exchanged the following HMAC key
+ value (expressed in base 64):
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>3iK5ZYAoBQuOqSgF/<WBR>YqlDw70HKRmbyXkrl5f4SJ4Toc=
+</PRE></DIV>
+<A name="0.2_anchor55"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.A.2"></A><H3>A.2.&nbsp;
+Client Requests Access Token</H3>
+
+<P>The Client makes an HTTPS POST to:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE><A href="https://auth.example.net/access_token" target="_blank">https://auth.example.net/<WBR>access_token</A>
+</PRE></DIV>
+<P>With the following message body:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>wrap_name=datadumper&amp;wrap_<WBR>password=j2hw7GPsl0&amp;Audience=<A href="http://crm.example.com/" target="_blank">c<WBR>rm.example.com</A>
+</PRE></DIV>
+<A name="0.2_anchor56"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.A.3"></A><H3>A.3.&nbsp;
+Successful Access Token Response from Authorization Server</H3>
+
+<P>The Authorization Server checks that the Client Password j2hw7GPsl0
+ is associated with the Client Name datadumper and that the Client is
+ authorized to access <A href="http://crm.example.com/" target="_blank">crm.example.com</A>. The Authorization Server notes
+ the time is 2010-02-03T04:05:06Z, which is 1265198706 seconds since
+ 1970-01-01T0:0:0Z. The Authorization Server would like the Access
+ Token to expire in an hour, so 3600 is added to the current time. The
+ Authorization Server then uses the values:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>net.example.auth.account:
+datadumper ExpiresOn: 1265202306 (1265198706 + 3600)
+Audience: <A href="http://crm.example.com/" target="_blank">crm.example.com</A>
+Issuer: <A href="http://auth.example.net/" target="_blank">auth.example.net</A>
+</PRE></DIV>
+<P>and the agreed HMAC key to generate the following SWT:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>net.example.auth.account=<WBR>datadumper&amp;ExpiresOn=<WBR>1265202306&amp;Audience=crm.
+<A href="http://example.com/" target="_blank">example.com</A>&amp;Issuer=<A href="http://auth.example.net/" target="_blank">auth.<WBR>example.net</A>&amp;HMACSHA256=N9%2F%<WBR>2F0tSos78Me36%2Bi
+oBH0sFKfd7eCsURlEIheoUbCJk%3D
+</PRE></DIV>
+<P>The Authorization Server then responds to the Clients HTTPS request
+ with:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>HTTP 200 OK
+</PRE></DIV>
+<P>and the Access Token and lifetime of the Access Token as
+ application/x-www-form-<WBR>urlencoded data in the body of the message as
+ such:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>wrap_access_token=net.example.<WBR>auth.account%3Ddatadumper%<WBR>26ExpiresOn%3D
+1265202306%26Audience%<A href="http://3dcrm.example.com/" target="_blank">3Dcrm.<WBR>example.com</A>%26Issuer%<A href="http://3dauth.example.net/" target="_blank">3Dauth.<WBR>example.net</A>%26
+HMACSHA256%3DN9%252F%<WBR>252F0tSos78Me36%<WBR>252BioBH0sFKfd7eCsURlEIheoUbCJ<WBR>k%2
+53D&amp;wrap_access_token_expires_<WBR>in=3600</PRE></DIV>
+<A name="0.2_anchor57"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.A.4"></A><H3>A.4.&nbsp;
+Client Calls Protected Resource</H3>
+
+<P>The Client now has an Access Token valid for an hour. The Client
+ makes an API call to:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE><A href="https://crm.example.com/data" target="_blank">https://crm.example.com/data</A>
+</PRE></DIV>
+<P>including the following HTTP header:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>Authorization: WRAP access_token="net.example.<WBR>auth.account=datadumper&amp;
+ExpiresOn=1265202306&amp;Audience=<A href="http://crm.example.com/" target="_blank"><WBR>crm.example.com</A>&amp;Issuer=<A href="http://auth.example.net/" target="_blank">auth.<WBR>example.net</A>&amp;
+HMACSHA256=N9%2F%<WBR>2F0tSos78Me36%<WBR>2BioBH0sFKfd7eCsURlEIheoUbCJk%<WBR>3D"
+</PRE></DIV>
+<P>The Protected Resources verifies the SWT and performs the Client's
+ request per the authorization attributes in the SWT.
+</P>
+<A name="0.2_anchor58"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.B"></A><H3>Appendix B.&nbsp;
+Web App Profile Example</H3>
+
+<P>In this example, Jane, the User, listens to music from
+ <A href="http://music.example.com/" target="_blank">music.example.com</A> and updates her status at <A href="http://status.example.com/" target="_blank">status.example.com</A>. When
+ listening to music, Jane would like her status to be updated at the
+ start of each song. From an OAuth WRAP perspective, the Client is
+ <A href="http://music.example.com/" target="_blank">music.example.com</A>, the Protected Resource is
+ <A href="https://status.example.com/update" target="_blank">https://status.example.com/<WBR>update</A>, and <A href="http://auth.example.com/" target="_blank">auth.example.com</A> is the
+ Authorization Server trusted by <A href="http://status.example.com/" target="_blank">status.example.com</A>.
+</P>
+<A name="0.2_anchor59"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.B.1"></A><H3>B.1.&nbsp;
+Provisioning</H3>
+
+<P>The Authorization Server documentation defines the following
+ URLs:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE> User Authorization URL: <A href="https://auth.example.com/user_authorization" target="_blank">https://auth.example.com/user_<WBR>authorization</A>
+ Access Token URL: <A href="https://auth.example.com/access_token" target="_blank">https://auth.example.com/<WBR>access_token</A>
+ Refresh Token URL: <A href="https://auth.example.com/refresh_token" target="_blank">https://auth.example.com/<WBR>refresh_token</A>
+</PRE></DIV>
+<P>The Authorization Server has defined that if the Client wants
+ authorization to update a User's status, that the Client include the
+ wrap_scope parameter with the value status_update when requesting
+ authorization.
+</P>
+<P>The Client has been provisioned with:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>Client Identifier: <A href="http://music.example.com/" target="_blank">music.example.com</A>
+Client Secret: 7F2986DF2342914A
+</PRE></DIV>
+<P>The Client has registered the Callback URL:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE><A href="https://music.example.com/auth_callback" target="_blank">https://music.example.com/<WBR>auth_callback</A>
+</PRE></DIV>
+<P>The Protected Resource and the Authorization Server have agreed to
+ use a Simple Web Token (SWT) for the Access Token with the reserved
+ attributes Issuer, Audience, ExpiresOn and the public attributes
+ com.example.auth.account, com.example.auth.client and
+ com.example.auth.scope. They have exchanged the following HMAC key
+ value (expressed in base 64):
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>Zt9JlL1QvPYRSCK9PgSjrxRUBWe7lb<WBR>EYsZCdM+sJCF4=
+</PRE></DIV>
+<A name="0.2_anchor60"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.B.2"></A><H3>B.2.&nbsp;
+Client Directs the User to the Server</H3>
+
+<P>Jane informs <A href="http://music.example.com/" target="_blank">music.example.com</A> that she would like her status at
+ <A href="http://status.example.com/" target="_blank">status.example.com</A> to be updated when a new song starts playing. The
+ <A href="http://music.example.com/" target="_blank">music.example.com</A> website maintains user sessions with a URL parameter
+ named session which has the value Vn3IG2FRALSEQX2Nxr at this time for
+ Jane. The Client will use wrap_client_state to maintain the session
+ value. The Client redirects Jane's browser to the Authorization
+ Server's User Authorization URL appending parameters for the Client
+ Identifier, Callback URL, Client state and authorization scope.
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE><A href="https://auth.example.com/user_authorization?wrap_client_id=music.example.com&wrap_callback=http%3A%2F%2Fmusic.example.com%2Fauth_callback&wrap_client_state=Vn3IG2FRALSEQX2Nxr&wrap_scope=status_update" target="_blank">https://auth.example.com/user_<WBR>authorization?wrap_client_id=<WBR>music.examp
+le.com&amp;wrap_callback=http%3A%<WBR>2F%2Fmusic.example.com%2Fauth_<WBR>callback&amp;wr
+ap_client_state=<WBR>Vn3IG2FRALSEQX2Nxr&amp;wrap_scope=<WBR>status_update</A>
+</PRE></DIV>
+<A name="0.2_anchor61"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.B.3"></A><H3>B.3.&nbsp;
+Authorization Server Confirms Delegation Request with User</H3>
+
+<P>The Authorization Server verifies the supplied Client Identifier
+ <A href="http://music.example.com/" target="_blank">music.example.com</A> has been registered and has the Callback URL
+ <A href="https://music.example.com/auth_callback" target="_blank">https://music.example.com/<WBR>auth_callback</A>. The Authorization Server
+ authenticates that the User it is dealing with is Jane, and then asks
+ Jane to authorize <A href="http://music.example.com/" target="_blank">music.example.com</A> to update Jane's status at
+ <A href="http://status.example.com/" target="_blank">status.example.com</A>. Jane approves the request and the Authorization
+ Server generates a Verification Code with the value 46YEXQjVit6T3nQ8,
+ stores it with the Client Identifier, Callback URl and the current
+ time.
+</P>
+<A name="0.2_anchor62"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.B.4"></A><H3>B.4.&nbsp;
+Server Directs User back to the Client</H3>
+
+<P>The Server redirects Jane back to the Client's Callback URL with
+ the Verification Code and Client State appended:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE><A href="https://music.example.com/auth_callback?wrap_verification_code=46YEXQjVit6T3nQ8&wrap_client_state=Vn3IG2FRALSEQX2Nxr" target="_blank">https://music.example.com/<WBR>auth_callback?wrap_<WBR>verification_code=46YEXQj
+Vit6T3nQ8&amp;wrap_client_state=<WBR>Vn3IG2FRALSEQX2Nxr</A>
+</PRE></DIV>
+<A name="0.2_anchor63"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.B.5"></A><H3>B.5.&nbsp;
+Client Requests Access Token</H3>
+
+<P>The Client makes an HTTPS POST request to:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE><A href="https://auth.example.com/access_token" target="_blank">https://auth.example.com/<WBR>access_token</A>
+</PRE></DIV>
+<P>With the following message body:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>wrap_client_id=<A href="http://music.example.com/" target="_blank">music.example.<WBR>com</A>&amp;wrap_client_secret=<WBR>7F2986DF2342914A&amp;w
+rap_verification_code=<WBR>46YEXQjVit6T3nQ8&amp;wrap_<WBR>callback=http%3A%2F%2Fmusi
+<A href="http://c.example.com/" target="_blank">c.example.com</A>%2Fauth_callback
+</PRE></DIV>
+<A name="0.2_anchor64"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.B.6"></A><H3>B.6.&nbsp;
+Successful Access Token Response from Authorization Server</H3>
+
+<P>The Authorization Server verifies that the Verification Code is
+ still valid, has not been used, and is associated with the Client ID,
+ Client Secret and Callback URL Password. The Authorization Server then
+ generates a Refresh Token with the value:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>MfdWTc+v9MXhpc+d/<WBR>csrKFMPfj1RySm6CzIjmTBGN6w=
+</PRE></DIV>
+<P>The Authorization Server notes the time is 2010-01-02T03:04:05Z,
+ which is 1262430245 seconds since 1970-01-01T0:0:0Z. The Authorization
+ Server then uses the values:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>com.example.auth.scope: status_updatea
+com.example.auth.account: Jane
+com.example.auth.client: <A href="http://music.example.com/" target="_blank">music.example.com</A>
+ExpiresOn: 1262433845 (1262430245 + 3600 seconds later)
+Audience: <A href="http://status.example.com/" target="_blank">status.example.com</A>
+Issuer: <A href="http://auth.example.com/" target="_blank">auth.example.com</A>
+</PRE></DIV>
+<P>and the agreed HMAC key to generate the following SWT:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>com.example.auth.scope=status_<WBR>update&amp;com.example.auth.<WBR>account=Jane&amp;com
+.example.auth.client=<A href="http://music.example.com/" target="_blank">music.<WBR>example.com</A>&amp;ExpiresOn=<WBR>1262433845&amp;Audience=s
+<A href="http://tatus.example.com/" target="_blank">tatus.example.com</A>&amp;Issuer=<A href="http://auth.example.com/" target="_blank">auth.<WBR>example.com</A>&amp;HMACSHA256=<WBR>3xZAYzJRtYCQgkAF3
+iqElp1DhyKkPhq947j04NcDocQ%3D
+</PRE></DIV>
+<P>The Authorization Server then responds to the Clients HTTPS request
+ with:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>HTTP 200 OK
+</PRE></DIV>
+<P>and the Refresh Token, Access Token and lifetime of the Access
+ Token as application/x-www-form-<WBR>urlencoded data in the body of the
+ message as such:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>wrap_refresh_token=MfdWTc%<WBR>2Bv9MXhpc%2Bd%<WBR>2FcsrKFMPfj1RySm6CzIjmTBGN6w%3
+D&amp;wrap_access_token=com.<WBR>example.auth.scope%3Dstatus_<WBR>update%26com.examp
+le.auth.account%3DJane%26com.<WBR>example.auth.client%<A href="http://3dmusic.example.com/" target="_blank">3Dmusic.<WBR>example.com</A>%2
+6ExpiresOn%3D1262433845%<WBR>26Audience%<A href="http://3dstatus.example.com/" target="_blank">3Dstatus.example.<WBR>com</A>%26Issuer%3Daut
+<A href="http://h.example.com/" target="_blank">h.example.com</A>%26HMACSHA256%<WBR>3D3xZAYzJRtYCQgkAF3iqElp1DhyKk<WBR>Phq947j04NcDo
+cQ%253D&amp;wrap_access_token_<WBR>expires_in=3600
+</PRE></DIV>
+<P>The Client now has a Refresh Token and Access Token valid for an
+ hour. The Client stores the Refresh Token for later use.
+</P>
+<A name="0.2_anchor65"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.B.7"></A><H3>B.7.&nbsp;
+Client Calls Protected Resource</H3>
+
+<P>A few minutes later, <A href="http://music.example.com/" target="_blank">music.example.com</A> starts playing a new song
+ for Jane. The Client updates Jane's status at <A href="http://status.example.com/" target="_blank">status.example.com</A> by
+ making an API call to:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE><A href="https://status.example.com/update" target="_blank">https://status.example.com/<WBR>update</A>
+</PRE></DIV>
+<P>including the following HTTP header:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>Authorization: WRAP access_token="com.example.<WBR>auth.scope=status_update
+&amp;com.example.auth.account=<WBR>Jane&amp;com.example.auth.client=<WBR>music.example.c
+om&amp;ExpiresOn=1262433845&amp;<WBR>Audience=<A href="http://status.example.com/" target="_blank">status.example.com</A>&amp;<WBR>Issuer=auth.exampl
+<A href="http://e.com/" target="_blank">e.com</A>&amp;HMACSHA256=<WBR>3xZAYzJRtYCQgkAF3iqElp1DhyKkPh<WBR>q947j04NcDocQ%3D"
+</PRE></DIV>
+<P>The Protected Resources verifies the SWT, confirms the
+ authorization contained in the SWT, and updates Jane's status.
+</P>
+<A name="0.2_anchor66"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<A name="0.2_rfc.section.B.8"></A><H3>B.8.&nbsp;
+Client Refreshes Access Token</H3>
+
+<P>An hour passes by and <A href="http://music.example.com/" target="_blank">music.example.com</A> starts playing another new
+ song for Jane. The Client again makes an API call to
+ <A href="http://status.example.com/" target="_blank">status.example.com</A> including the same HTTP Authorization header.
+ Unlike previous calls where the status update was performed, the
+ Protected Resource returns the following error response:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>HTTP 401 Unauthorized
+</PRE></DIV>
+<P>and the HTTP header:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>WWW-Authenticate: WRAP
+</PRE></DIV>
+<P>The Client determines it probably needs a new Access Token,
+ retrieves the Refresh Token and makes an HTTPS POST to:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE><A href="https://auth.example.com/refresh_token" target="_blank">https://auth.example.com/<WBR>refresh_token</A>
+</PRE></DIV>
+<P>including the Client Identifier, Client Secret and Refresh Token in
+ the message body as:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>wrap_client_id=<A href="http://music.example.com/" target="_blank">music.example.<WBR>com</A>&amp;wrap_client_secret=<WBR>7F2986DF2342914A&amp;w
+rap_refresh_token=MfdWTc%<WBR>2Bv9MXhpc%2Bd%<WBR>2FcsrKFMPfj1RySm6CzIjmTBGN6w%<WBR>3D
+</PRE></DIV>
+<P>The Authorization Server looks up the data associated with the
+ Refresh Token, determines <A href="http://music.example.com/" target="_blank">music.example.com</A> is still authorized to
+ update Jane's status, and determines it will generate a new Access
+ Token for the Client that expires in an hour. The time is now
+ 2010-01-02T04:15:23Z, which results in an Access Token expiry time of
+ 1262438123 seconds since 1970-01-01T0:0:0Z. The Authorization Server
+ generates a new Access Token and returns it in the body of the message
+ as:
+</P><DIV style="display:table;width:0;margin-left:3em;margin-right:auto"><PRE>wrap_access_token=com.example.<WBR>auth.scope=status_update&amp;com.<WBR>example.aut
+h.account=Jane&amp;com.example.<WBR>auth.client=<A href="http://music.example.com/" target="_blank">music.example.com</A>&amp;<WBR>ExpiresOn=126
+2438123&amp;Audience=<A href="http://status.example.com/" target="_blank">status.<WBR>example.com</A>&amp;Issuer=<A href="http://auth.example.com/" target="_blank">auth.<WBR>example.com</A>&amp;HMACSHA256
+=<WBR>AT4TFChHgyylItEWAjK7MFRJuvUS3W<WBR>LVzO%2F68gvIRQI%3D&amp;wrap_<WBR>access_token_ex
+pires_in=3600
+</PRE></DIV>
+<P>The Client takes the new Access Token and uses it to successfully
+ update Jane's status at <A href="http://status.example.com/" target="_blank">status.example.com</A>.
+</P>
+<A name="0.2_rfc.authors"></A><BR><HR>
+<TABLE summary="layout" cellpadding="0" cellspacing="2" align="right"><TBODY><TR><TD><A href="https://mail.google.com/mail/?ui=2&ik=c5d0d94d4a&view=att&th=12634202598d2cea&attid=0.2&disp=inline&realattid=f_g4hjnq761&zw#0.2_toc">&nbsp;TOC&nbsp;</A></TD></TR></TBODY></TABLE>
+<H3>Authors' Addresses</H3>
+<TABLE width="99%" border="0" cellpadding="0" cellspacing="0">
+<TBODY><TR><TD>&nbsp;</TD>
+<TD>Dick Hardt (editor)</TD></TR>
+<TR><TD>&nbsp;</TD>
+<TD>Microsoft</TD></TR>
+<TR><TD align="right">Email:&nbsp;</TD>
+<TD><A href="mailto:dick.hardt@gmail.com" target="_blank">dick.hardt@gmail.com</A></TD></TR>
+<TR cellpadding="3"><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>
+<TR><TD>&nbsp;</TD>
+<TD>Allen Tom</TD></TR>
+<TR><TD>&nbsp;</TD>
+<TD>Yahoo!</TD></TR>
+<TR><TD align="right">Email:&nbsp;</TD>
+<TD><A href="mailto:atom@yahoo-inc.com" target="_blank">atom@yahoo-inc.com</A></TD></TR>
+<TR cellpadding="3"><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>
+<TR><TD>&nbsp;</TD>
+<TD>Brian Eaton</TD></TR>
+<TR><TD>&nbsp;</TD>
+<TD>Google</TD></TR>
+<TR><TD align="right">Email:&nbsp;</TD>
+<TD><A href="mailto:beaton@google.com" target="_blank">beaton@google.com</A></TD></TR>
+<TR cellpadding="3"><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>
+<TR><TD>&nbsp;</TD>
+<TD>Yaron Goland</TD></TR>
+<TR><TD>&nbsp;</TD>
+<TD>Microsoft</TD></TR>
+<TR><TD align="right">Email:&nbsp;</TD>
+<TD><A href="mailto:yarong@microsoft.com" target="_blank">yarong@microsoft.com</A></TD></TR>
+</TBODY></TABLE>
+</DIV>
+
+</BODY></HTML> \ No newline at end of file
diff --git a/src/DotNetOpenAuth.Test/Mocks/TestDirectResponseMessageWithHttpStatus.cs b/src/DotNetOpenAuth.Test/Mocks/TestDirectResponseMessageWithHttpStatus.cs
index d692320..20fd6c4 100644
--- a/src/DotNetOpenAuth.Test/Mocks/TestDirectResponseMessageWithHttpStatus.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/TestDirectResponseMessageWithHttpStatus.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.Test.Mocks {
using System;
using System.Collections.Generic;
using System.Linq;
+ using System.Net;
using System.Text;
using DotNetOpenAuth.Messaging;
@@ -23,8 +24,15 @@ namespace DotNetOpenAuth.Test.Mocks {
/// <summary>
/// Gets or sets the HTTP status code that the direct respones should be sent with.
/// </summary>
- /// <value></value>
- public System.Net.HttpStatusCode HttpStatusCode { get; set; }
+ public HttpStatusCode HttpStatusCode { get; set; }
+
+ /// <summary>
+ /// Gets the HTTP headers to add to the response.
+ /// </summary>
+ /// <value>May be an empty collection, but must not be <c>null</c>.</value>
+ public WebHeaderCollection Headers {
+ get { return new WebHeaderCollection(); }
+ }
#endregion
}
diff --git a/src/DotNetOpenAuth.sln b/src/DotNetOpenAuth.sln
index 55d43e8..135d51f 100644
--- a/src/DotNetOpenAuth.sln
+++ b/src/DotNetOpenAuth.sln
@@ -13,6 +13,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Specs", "Specs", "{CD57219F-24F4-4136-8741-6063D0D7A031}"
ProjectSection(SolutionItems) = preProject
+ ..\doc\specs\draft-hardt-oauth-01.htm = ..\doc\specs\draft-hardt-oauth-01.htm
..\doc\specs\ICAM_OpenID20Profile.pdf = ..\doc\specs\ICAM_OpenID20Profile.pdf
..\doc\specs\OAuth Core 1.0.htm = ..\doc\specs\OAuth Core 1.0.htm
..\doc\specs\OAuth Core 1.0a (Draft 3).htm = ..\doc\specs\OAuth Core 1.0a (Draft 3).htm
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
index 80487fc..7f5b298 100644
--- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
@@ -224,13 +224,13 @@ http://opensource.org/licenses/ms-pl.html
</Reference>
</ItemGroup>
<ItemGroup Condition=" '$(ClrVersion)' == '4' ">
- <Reference Include="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/>
+ <Reference Include="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
</ItemGroup>
<ItemGroup Condition=" '$(ClrVersion)' != '4' ">
<!-- MVC 2 can run on CLR 2 (it doesn't require CLR 4) but since MVC 2 apps tend to use type forwarding,
it's a more broadly consumable idea to bind against MVC 1 for the library unless we're building on CLR 4,
which will definitely have MVC 2 available. -->
- <Reference Include="System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/>
+ <Reference Include="System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
</ItemGroup>
<ItemGroup>
<Compile Include="ComponentModel\ClaimTypeSuggestions.cs" />
@@ -284,6 +284,7 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="Messaging\HostErrorException.cs" />
<Compile Include="Messaging\IHttpDirectResponse.cs" />
<Compile Include="Messaging\IExtensionMessage.cs" />
+ <Compile Include="Messaging\IHttpDirectResponseContract.cs" />
<Compile Include="Messaging\IMessage.cs" />
<Compile Include="Messaging\IncomingWebResponse.cs" />
<Compile Include="Messaging\IDirectResponseProtocolMessage.cs" />
@@ -302,6 +303,28 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="Messaging\Reflection\IMessagePartEncoder.cs" />
<Compile Include="Messaging\Reflection\IMessagePartNullEncoder.cs" />
<Compile Include="Messaging\Reflection\MessageDescriptionCollection.cs" />
+ <Compile Include="OAuthWrap\IClientTokenManager.cs" />
+ <Compile Include="OAuthWrap\Messages\Assertion\AssertionRequest.cs" />
+ <Compile Include="OAuthWrap\Messages\Assertion\AssertionFailedResponse.cs" />
+ <Compile Include="OAuthWrap\Messages\ClientAccountAndPassword\ClientAccountUsernamePasswordFailedResponse.cs" />
+ <Compile Include="OAuthWrap\Messages\ClientAccountAndPassword\ClientAccountUsernamePasswordRequest.cs" />
+ <Compile Include="OAuthWrap\Messages\ClientAccountAndPassword\ClientAccountUsernamePasswordSuccessResponse.cs" />
+ <Compile Include="OAuthWrap\Messages\Assertion\AssertionSuccessResponse.cs" />
+ <Compile Include="OAuthWrap\Messages\IMessageWithClientState.cs" />
+ <Compile Include="OAuthWrap\Messages\RichApp\RichAppAccessTokenRequest.cs" />
+ <Compile Include="OAuthWrap\Messages\RichApp\RichAppRequest.cs" />
+ <Compile Include="OAuthWrap\Messages\RichApp\RichAppResponse.cs" />
+ <Compile Include="OAuthWrap\Messages\RichApp\RichAppAccessTokenSuccessResponse.cs" />
+ <Compile Include="OAuthWrap\Messages\RichApp\RichAppAccessTokenFailedResponse.cs" />
+ <Compile Include="OAuthWrap\Messages\UnauthorizedResponse.cs" />
+ <Compile Include="OAuthWrap\Messages\RefreshAccessTokenFailedResponse.cs" />
+ <Compile Include="OAuthWrap\Messages\RefreshAccessTokenSuccessResponse.cs" />
+ <Compile Include="OAuthWrap\Messages\RefreshAccessTokenRequest.cs" />
+ <Compile Include="OAuthWrap\Messages\UsernameAndPassword\UserNamePasswordCaptchaResponse.cs" />
+ <Compile Include="OAuthWrap\Messages\UsernameAndPassword\UserNamePasswordVerificationResponse.cs" />
+ <Compile Include="OAuthWrap\Messages\WebApp\WebAppAccessTokenBadClientResponse.cs" />
+ <Compile Include="OAuthWrap\Messages\WebApp\WebAppAccessTokenFailedResponse.cs" />
+ <Compile Include="OAuthWrap\WrapUtilities.cs" />
<Compile Include="OAuth\ChannelElements\ICombinedOpenIdProviderTokenManager.cs" />
<Compile Include="OAuth\ChannelElements\IConsumerDescription.cs" />
<Compile Include="OAuth\ChannelElements\IConsumerTokenManager.cs" />
@@ -445,7 +468,7 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="OpenId\Extensions\ProviderAuthenticationPolicy\PapeUtilities.cs" />
<Compile Include="OpenId\Extensions\ProviderAuthenticationPolicy\PolicyRequest.cs" />
<Compile Include="OpenId\Extensions\ProviderAuthenticationPolicy\PolicyResponse.cs" />
- <Compile Include="OpenId\Extensions\ProviderAuthenticationPolicy\TimespanSecondsEncoder.cs" />
+ <Compile Include="Messaging\TimespanSecondsEncoder.cs" />
<Compile Include="OpenId\Extensions\SimpleRegistration\ClaimsRequest.cs" />
<Compile Include="OpenId\Extensions\SimpleRegistration\ClaimsResponse.cs" />
<Compile Include="OpenId\Extensions\SimpleRegistration\Constants.cs" />
@@ -586,6 +609,26 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="Messaging\StandardWebRequestHandler.cs" />
<Compile Include="Messaging\MessageReceivingEndpoint.cs" />
<Compile Include="Reporting.cs" />
+ <Compile Include="OAuthWrap\ChannelElements\OAuthWrapChannel.cs" />
+ <Compile Include="OAuthWrap\ChannelElements\OAuthWrapMessageFactory.cs" />
+ <Compile Include="OAuthWrap\ClientBase.cs" />
+ <Compile Include="OAuthWrap\Messages\WebApp\WebAppAccessTokenSuccessResponse.cs" />
+ <Compile Include="OAuthWrap\Messages\MessageBase.cs" />
+ <Compile Include="OAuthWrap\Messages\WebApp\WebAppAccessTokenRequest.cs" />
+ <Compile Include="OAuthWrap\Messages\WebApp\WebAppFailedResponse.cs" />
+ <Compile Include="OAuthWrap\Messages\WebApp\WebAppRequest.cs" />
+ <Compile Include="OAuthWrap\Messages\WebApp\WebAppSuccessResponse.cs" />
+ <Compile Include="OAuthWrap\Messages\UsernameAndPassword\UserNamePasswordFailedResponse.cs" />
+ <Compile Include="OAuthWrap\Messages\UsernameAndPassword\UserNamePasswordRequest.cs" />
+ <Compile Include="OAuthWrap\Messages\UsernameAndPassword\UserNamePasswordSuccessResponse.cs" />
+ <Compile Include="OAuthWrap\Protocol.cs" />
+ <Compile Include="OAuthWrap\OAuthWrapStrings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>OAuthWrapStrings.resx</DependentUpon>
+ </Compile>
+ <Compile Include="OAuthWrap\AuthorizationServerDescription.cs" />
+ <Compile Include="OAuthWrap\WebAppClient.cs" />
<Compile Include="Util.cs" />
<Compile Include="OAuth\Protocol.cs" />
<Compile Include="OAuth\ServiceProvider.cs" />
@@ -698,6 +741,10 @@ http://opensource.org/licenses/ms-pl.html
<EmbeddedResource Include="OpenId\RelyingParty\OpenIdRelyingPartyAjaxControlBase.js">
<Copyright>$(StandardCopyright)</Copyright>
</EmbeddedResource>
+ <EmbeddedResource Include="OAuthWrap\OAuthWrapStrings.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>OAuthWrapStrings.Designer.cs</LastGenOutput>
+ </EmbeddedResource>
<EmbeddedResource Include="Strings.sr.resx" />
<EmbeddedResource Include="Xrds\XrdsStrings.sr.resx" />
</ItemGroup>
diff --git a/src/DotNetOpenAuth/Messaging/IHttpDirectResponse.cs b/src/DotNetOpenAuth/Messaging/IHttpDirectResponse.cs
index c0e7803..20c3d6f 100644
--- a/src/DotNetOpenAuth/Messaging/IHttpDirectResponse.cs
+++ b/src/DotNetOpenAuth/Messaging/IHttpDirectResponse.cs
@@ -5,16 +5,24 @@
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.Messaging {
+ using System.Diagnostics.Contracts;
using System.Net;
/// <summary>
/// An interface that allows direct response messages to specify
/// HTTP transport specific properties.
/// </summary>
+ [ContractClass(typeof(IHttpDirectResponseContract))]
public interface IHttpDirectResponse {
/// <summary>
- /// Gets the HTTP status code that the direct respones should be sent with.
+ /// Gets the HTTP status code that the direct response should be sent with.
/// </summary>
HttpStatusCode HttpStatusCode { get; }
+
+ /// <summary>
+ /// Gets the HTTP headers to add to the response.
+ /// </summary>
+ /// <value>May be an empty collection, but must not be <c>null</c>.</value>
+ WebHeaderCollection Headers { get; }
}
}
diff --git a/src/DotNetOpenAuth/Messaging/IHttpDirectResponseContract.cs b/src/DotNetOpenAuth/Messaging/IHttpDirectResponseContract.cs
new file mode 100644
index 0000000..b1ddba2
--- /dev/null
+++ b/src/DotNetOpenAuth/Messaging/IHttpDirectResponseContract.cs
@@ -0,0 +1,43 @@
+//-----------------------------------------------------------------------
+// <copyright file="IHttpDirectResponseContract.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Messaging {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using System.Linq;
+ using System.Net;
+ using System.Text;
+
+ /// <summary>
+ /// Contract class for the <see cref="IHttpDirectResponse"/> interface.
+ /// </summary>
+ [ContractClassFor(typeof(IHttpDirectResponse))]
+ public abstract class IHttpDirectResponseContract : IHttpDirectResponse {
+ #region IHttpDirectResponse Members
+
+ /// <summary>
+ /// Gets the HTTP status code that the direct response should be sent with.
+ /// </summary>
+ /// <value></value>
+ HttpStatusCode IHttpDirectResponse.HttpStatusCode {
+ get { throw new NotImplementedException(); }
+ }
+
+ /// <summary>
+ /// Gets the HTTP headers to add to the response.
+ /// </summary>
+ /// <value>May be an empty collection, but must not be <c>null</c>.</value>
+ WebHeaderCollection IHttpDirectResponse.Headers {
+ get {
+ Contract.Ensures(Contract.Result<WebHeaderCollection>() != null);
+ throw new NotImplementedException();
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/TimespanSecondsEncoder.cs b/src/DotNetOpenAuth/Messaging/TimespanSecondsEncoder.cs
index cc3f7cc..3ad1bd8 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/TimespanSecondsEncoder.cs
+++ b/src/DotNetOpenAuth/Messaging/TimespanSecondsEncoder.cs
@@ -4,7 +4,7 @@
// </copyright>
//-----------------------------------------------------------------------
-namespace DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy {
+namespace DotNetOpenAuth.Messaging {
using System;
using System.Globalization;
using DotNetOpenAuth.Messaging.Reflection;
@@ -13,6 +13,12 @@ namespace DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy {
/// Encodes and decodes the <see cref="TimeSpan"/> as an integer of total seconds.
/// </summary>
internal class TimespanSecondsEncoder : IMessagePartEncoder {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TimespanSecondsEncoder"/> class.
+ /// </summary>
+ internal TimespanSecondsEncoder() {
+ }
+
#region IMessagePartEncoder Members
/// <summary>
diff --git a/src/DotNetOpenAuth/OAuth/Protocol.cs b/src/DotNetOpenAuth/OAuth/Protocol.cs
index a524ba7..71a25f8 100644
--- a/src/DotNetOpenAuth/OAuth/Protocol.cs
+++ b/src/DotNetOpenAuth/OAuth/Protocol.cs
@@ -100,7 +100,7 @@ namespace DotNetOpenAuth.OAuth {
}
/// <summary>
- /// Gets the version used to represent OAuth 1.0a.
+ /// Gets the OAuth version this instance represents.
/// </summary>
internal Version Version { get; private set; }
diff --git a/src/DotNetOpenAuth/OAuthWrap/AuthorizationServerDescription.cs b/src/DotNetOpenAuth/OAuthWrap/AuthorizationServerDescription.cs
new file mode 100644
index 0000000..c04cec0
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/AuthorizationServerDescription.cs
@@ -0,0 +1,64 @@
+//-----------------------------------------------------------------------
+// <copyright file="AuthorizationServerDescription.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+
+ /// <summary>
+ /// A description of an OAuth WRAP Authorization Server.
+ /// </summary>
+ public class AuthorizationServerDescription {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AuthorizationServerDescription"/> class.
+ /// </summary>
+ public AuthorizationServerDescription() {
+ this.ProtocolVersion = Protocol.Default.ProtocolVersion;
+ }
+
+ /// <summary>
+ /// Gets or sets the Authorization Server URL at which an Access Token is requested by the Client.
+ /// A refresh token may also be returned to the Client.
+ /// </summary>
+ /// <value>An HTTPS URL.</value>
+ /// <remarks>
+ /// Messages sent to this URL must always be sent by the POST HTTP method.
+ /// </remarks>
+ public Uri AccessTokenEndpoint { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Authorization Server URL at which a Refresh Token is presented in exchange
+ /// for a new Access Token.
+ /// </summary>
+ /// <value>An HTTPS URL.</value>
+ /// <remarks>
+ /// Messages sent to this URL must always be sent by the POST HTTP method.
+ /// </remarks>
+ public Uri RefreshTokenEndpoint { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Authorization Server URL where the Client (re)directs the User
+ /// to make an authorization request.
+ /// </summary>
+ /// <value>An HTTP or HTTPS URL.</value>
+ public Uri UserAuthorizationEndpoint { get; set; }
+
+ /// <summary>
+ /// Gets or sets the OAuth WRAP version supported by the Authorization Server.
+ /// </summary>
+ public ProtocolVersion ProtocolVersion { get; set; }
+
+ /// <summary>
+ /// Gets the version of the OAuth WRAP protocol to use with this Authorization Server.
+ /// </summary>
+ /// <value>The version.</value>
+ internal Version Version {
+ get { return Protocol.Lookup(this.ProtocolVersion).Version; }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapChannel.cs b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapChannel.cs
new file mode 100644
index 0000000..3c2065f
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapChannel.cs
@@ -0,0 +1,52 @@
+//-----------------------------------------------------------------------
+// <copyright file="OAuthWrapChannel.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.ChannelElements {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// The channel for the OAuth WRAP protocol.
+ /// </summary>
+ internal class OAuthWrapChannel : Channel {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="OAuthWrapChannel"/> class.
+ /// </summary>
+ internal OAuthWrapChannel()
+ : base(new OAuthWrapMessageFactory()) {
+ }
+
+ /// <summary>
+ /// Gets the protocol message that may be in the given HTTP response.
+ /// </summary>
+ /// <param name="response">The response that is anticipated to contain an protocol message.</param>
+ /// <returns>
+ /// The deserialized message parts, if found. Null otherwise.
+ /// </returns>
+ /// <exception cref="ProtocolException">Thrown when the response is not valid.</exception>
+ protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebResponse response) {
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// Queues a message for sending in the response stream where the fields
+ /// are sent in the response stream in querystring style.
+ /// </summary>
+ /// <param name="response">The message to send as a response.</param>
+ /// <returns>
+ /// The pending user agent redirect based message to be sent as an HttpResponse.
+ /// </returns>
+ /// <remarks>
+ /// This method implements spec OAuth V1.0 section 5.3.
+ /// </remarks>
+ protected override OutgoingWebResponse PrepareDirectResponse(IProtocolMessage response) {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapMessageFactory.cs b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapMessageFactory.cs
new file mode 100644
index 0000000..b3b9abb
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/ChannelElements/OAuthWrapMessageFactory.cs
@@ -0,0 +1,99 @@
+//-----------------------------------------------------------------------
+// <copyright file="OAuthWrapMessageFactory.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.ChannelElements {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OAuthWrap.Messages;
+
+ /// <summary>
+ /// The message factory for OAuth WRAP messages.
+ /// </summary>
+ internal class OAuthWrapMessageFactory : IMessageFactory {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="OAuthWrapMessageFactory"/> class.
+ /// </summary>
+ internal OAuthWrapMessageFactory() {
+ }
+
+ #region IMessageFactory Members
+
+ /// <summary>
+ /// Analyzes an incoming request message payload to discover what kind of
+ /// message is embedded in it and returns the type, or null if no match is found.
+ /// </summary>
+ /// <param name="recipient">The intended or actual recipient of the request message.</param>
+ /// <param name="fields">The name/value pairs that make up the message payload.</param>
+ /// <returns>
+ /// A newly instantiated <see cref="IProtocolMessage"/>-derived object that this message can
+ /// deserialize to. Null if the request isn't recognized as a valid protocol message.
+ /// </returns>
+ public IDirectedProtocolMessage GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary<string, string> fields) {
+ Version version = Protocol.DefaultVersion;
+
+ if (fields.ContainsKey(Protocol.wrap_client_id) && fields.ContainsKey(Protocol.wrap_callback)) {
+ return new WebAppRequest(recipient.Location, version);
+ }
+
+ if (fields.ContainsKey(Protocol.wrap_client_id) && fields.ContainsKey(Protocol.wrap_verification_code)) {
+ return new WebAppAccessTokenRequest(recipient.Location, version);
+ }
+
+ if (fields.ContainsKey(Protocol.wrap_name)) {
+ return new ClientAccountUsernamePasswordRequest(recipient.Location, version);
+ }
+
+ if (fields.ContainsKey(Protocol.wrap_username)) {
+ return new UserNamePasswordRequest(recipient.Location, version);
+ }
+
+ if (fields.ContainsKey(Protocol.wrap_verification_code)) {
+ return new WebAppSuccessResponse(recipient.Location, version);
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Analyzes an incoming request message payload to discover what kind of
+ /// message is embedded in it and returns the type, or null if no match is found.
+ /// </summary>
+ /// <param name="request">The message that was sent as a request that resulted in the response.</param>
+ /// <param name="fields">The name/value pairs that make up the message payload.</param>
+ /// <returns>
+ /// A newly instantiated <see cref="IProtocolMessage"/>-derived object that this message can
+ /// deserialize to. Null if the request isn't recognized as a valid protocol message.
+ /// </returns>
+ public IDirectResponseProtocolMessage GetNewResponseMessage(IDirectedProtocolMessage request, IDictionary<string, string> fields) {
+ Version version = Protocol.DefaultVersion;
+
+ var accessTokenRequest = request as WebAppAccessTokenRequest;
+ if (accessTokenRequest != null) {
+ if (fields.ContainsKey(Protocol.wrap_access_token)) {
+ return new WebAppAccessTokenSuccessResponse(accessTokenRequest);
+ } else {
+ //return new AccessTokenWithVerificationCodeFailedResponse(accessTokenRequest);
+ }
+ }
+
+ var userAuthorization = request as UserNamePasswordRequest;
+ if (userAuthorization != null) {
+ if (fields.ContainsKey(Protocol.wrap_verification_code)) {
+ return new UserNamePasswordSuccessResponse(userAuthorization);
+ } else {
+ //return new UserAuthorizationViaUsernamePasswordFailedResponse(userAuthorization);
+ }
+ }
+
+ return null;
+ }
+
+ #endregion
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/ClientBase.cs b/src/DotNetOpenAuth/OAuthWrap/ClientBase.cs
new file mode 100644
index 0000000..a36759d
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/ClientBase.cs
@@ -0,0 +1,54 @@
+//-----------------------------------------------------------------------
+// <copyright file="ClientBase.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using System.Linq;
+ using System.Net;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A base class for common OAuth WRAP Consumer behaviors.
+ /// </summary>
+ public class ClientBase {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ClientBase"/> class.
+ /// </summary>
+ /// <param name="authorizationServer">The token issuer.</param>
+ protected ClientBase(AuthorizationServerDescription authorizationServer) {
+ Contract.Requires<ArgumentNullException>(authorizationServer != null);
+ this.AuthorizationServer = authorizationServer;
+ }
+
+ /// <summary>
+ /// Gets the token issuer.
+ /// </summary>
+ /// <value>The token issuer.</value>
+ public AuthorizationServerDescription AuthorizationServer { get; private set; }
+
+ /// <summary>
+ /// Gets the OAuth WRAP channel.
+ /// </summary>
+ /// <value>The channel.</value>
+ public Channel Channel { get; private set; }
+
+ /// <summary>
+ /// Adds the necessary HTTP Authorization header to an HTTP request for protected resources
+ /// so that the Service Provider will allow the request through.
+ /// </summary>
+ /// <param name="request">The request for protected resources from the service provider.</param>
+ /// <param name="accessToken">The access token previously obtained from the Authorization Server.</param>
+ public static void AuthorizeRequest(HttpWebRequest request, string accessToken) {
+ Contract.Requires<ArgumentNullException>(request != null);
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(accessToken));
+ WrapUtilities.AuthorizeWithOAuthWrap(request, accessToken);
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/IClientTokenManager.cs b/src/DotNetOpenAuth/OAuthWrap/IClientTokenManager.cs
new file mode 100644
index 0000000..4cedaee
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/IClientTokenManager.cs
@@ -0,0 +1,43 @@
+//-----------------------------------------------------------------------
+// <copyright file="IClientTokenManager.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+using System.Diagnostics.Contracts;
+
+ [ContractClass(typeof(IClientTokenManagerContract))]
+ public interface IClientTokenManager {
+ IWrapAuthorization GetAuthorizationState(Uri callbackUrl, string clientState);
+ }
+
+ internal class IClientTokenManagerContract : IClientTokenManager {
+ private IClientTokenManagerContract() {
+ }
+
+ #region IClientTokenManager Members
+
+ IWrapAuthorization IClientTokenManager.GetAuthorizationState(Uri callbackUrl, string clientState) {
+ Contract.Requires<ArgumentNullException>(callbackUrl != null);
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+
+
+ public interface IWrapAuthorization {
+ Uri Callback { get; set; }
+ string RefreshToken { get; set; }
+ string AccessToken { get; set; }
+ DateTime? AccessTokenExpirationUtc { get; set; }
+ string Scope { get; set; }
+
+ void Delete();
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionFailedResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionFailedResponse.cs
new file mode 100644
index 0000000..020192e
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionFailedResponse.cs
@@ -0,0 +1,21 @@
+//-----------------------------------------------------------------------
+// <copyright file="AssertionFailedResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ /// <summary>
+ /// A response from the Authorization Server to the Client to indicate that a
+ /// request for an access code failed, probably due to an invalid assertion.
+ /// </summary>
+ internal class AssertionFailedResponse : UnauthorizedResponse {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AssertionFailedResponse"/> class.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ internal AssertionFailedResponse(AssertionRequest request)
+ : base(request) {
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionRequest.cs
new file mode 100644
index 0000000..cfd537a
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionRequest.cs
@@ -0,0 +1,65 @@
+//-----------------------------------------------------------------------
+// <copyright file="AssertionRequest.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A request from a Client to an Authorization Server with some assertion for an access token.
+ /// </summary>
+ internal class AssertionRequest : MessageBase {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AssertionRequest"/> class.
+ /// </summary>
+ /// <param name="version">The version.</param>
+ /// <param name="authorizationServer">The authorization server.</param>
+ internal AssertionRequest(Version version, Uri authorizationServer)
+ : base(version, MessageTransport.Direct, authorizationServer) {
+ this.HttpMethods = HttpDeliveryMethods.PostRequest;
+ }
+
+ /// <summary>
+ /// Gets or sets the format of the assertion as defined by the Authorization Server.
+ /// </summary>
+ /// <value>The assertion format.</value>
+ [MessagePart(Protocol.wrap_assertion_format, IsRequired = true, AllowEmpty = false)]
+ internal string AssertionFormat { get; set; }
+
+ /// <summary>
+ /// Gets or sets the assertion.
+ /// </summary>
+ /// <value>The assertion.</value>
+ [MessagePart(Protocol.wrap_assertion, IsRequired = true, AllowEmpty = false)]
+ internal string Assertion { get; set; }
+
+ /// <summary>
+ /// Gets or sets an optional authorization scope as defined by the Authorization Server.
+ /// </summary>
+ [MessagePart(Protocol.wrap_scope, IsRequired = false, AllowEmpty = true)]
+ internal string Scope { get; set; }
+
+ /// <summary>
+ /// Checks the message state for conformity to the protocol specification
+ /// and throws an exception if the message is invalid.
+ /// </summary>
+ /// <remarks>
+ /// <para>Some messages have required fields, or combinations of fields that must relate to each other
+ /// in specialized ways. After deserializing a message, this method checks the state of the
+ /// message to see if it conforms to the protocol.</para>
+ /// <para>Note that this property should <i>not</i> check signatures or perform any state checks
+ /// outside this scope of this particular message.</para>
+ /// </remarks>
+ /// <exception cref="ProtocolException">Thrown if the message is invalid.</exception>
+ protected override void EnsureValidMessage() {
+ base.EnsureValidMessage();
+ ErrorUtilities.VerifyProtocol(this.Recipient.IsTransportSecure(), OAuthWrapStrings.HttpsRequired);
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionSuccessResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionSuccessResponse.cs
new file mode 100644
index 0000000..a934c07
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/Assertion/AssertionSuccessResponse.cs
@@ -0,0 +1,40 @@
+//-----------------------------------------------------------------------
+// <copyright file="AssertionSuccessResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A response from the Authorization Server to the Client containing an access code.
+ /// </summary>
+ internal class AssertionSuccessResponse : MessageBase {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AssertionSuccessResponse"/> class.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ internal AssertionSuccessResponse(ClientAccountUsernamePasswordRequest request)
+ : base(request) {
+ }
+
+ /// <summary>
+ /// Gets or sets the access token.
+ /// </summary>
+ /// <value>The access token.</value>
+ [MessagePart(Protocol.wrap_access_token, IsRequired = true, AllowEmpty = false)]
+ internal string AccessToken { get; set; }
+
+ /// <summary>
+ /// Gets or sets the lifetime of the access token.
+ /// </summary>
+ /// <value>The lifetime.</value>
+ [MessagePart(Protocol.wrap_access_token_expires_in, IsRequired = false, Encoder = typeof(TimespanSecondsEncoder))]
+ internal TimeSpan Lifetime { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/ClientAccountAndPassword/ClientAccountUsernamePasswordFailedResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/ClientAccountAndPassword/ClientAccountUsernamePasswordFailedResponse.cs
new file mode 100644
index 0000000..57ce588
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/ClientAccountAndPassword/ClientAccountUsernamePasswordFailedResponse.cs
@@ -0,0 +1,22 @@
+//-----------------------------------------------------------------------
+// <copyright file="ClientAccountUsernamePasswordFailedResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ /// <summary>
+ /// A response from the Authorization Server to the Client to indicate that a
+ /// request for an access code failed, probably due to an invalid account
+ /// name and password.
+ /// </summary>
+ internal class ClientAccountUsernamePasswordFailedResponse : UnauthorizedResponse {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ClientAccountUsernamePasswordFailedResponse"/> class.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ internal ClientAccountUsernamePasswordFailedResponse(ClientAccountUsernamePasswordRequest request)
+ : base(request) {
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/ClientAccountAndPassword/ClientAccountUsernamePasswordRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/ClientAccountAndPassword/ClientAccountUsernamePasswordRequest.cs
new file mode 100644
index 0000000..9f47c57
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/ClientAccountAndPassword/ClientAccountUsernamePasswordRequest.cs
@@ -0,0 +1,69 @@
+//-----------------------------------------------------------------------
+// <copyright file="ClientAccountUsernamePasswordRequest.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A request for an access token for a client application that has its
+ /// own (non-user affiliated) client name and password.
+ /// </summary>
+ /// <remarks>
+ /// This is somewhat analogous to 2-legged OAuth.
+ /// </remarks>
+ internal class ClientAccountUsernamePasswordRequest : MessageBase {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ClientAccountUsernamePasswordRequest"/> class.
+ /// </summary>
+ /// <param name="authorizationServer">The authorization server.</param>
+ /// <param name="version">The version.</param>
+ internal ClientAccountUsernamePasswordRequest(Uri authorizationServer, Version version)
+ : base(version, MessageTransport.Direct, authorizationServer) {
+ this.HttpMethods = HttpDeliveryMethods.PostRequest;
+ }
+
+ /// <summary>
+ /// Gets or sets the account name.
+ /// </summary>
+ /// <value>The name on the account.</value>
+ [MessagePart(Protocol.wrap_name, IsRequired = true, AllowEmpty = false)]
+ internal string Name { get; set; }
+
+ /// <summary>
+ /// Gets or sets the user's password.
+ /// </summary>
+ /// <value>The password.</value>
+ [MessagePart(Protocol.wrap_password, IsRequired = true, AllowEmpty = false)]
+ internal string Password { get; set; }
+
+ /// <summary>
+ /// Gets or sets an optional authorization scope as defined by the Authorization Server.
+ /// </summary>
+ [MessagePart(Protocol.wrap_scope, IsRequired = false, AllowEmpty = true)]
+ internal string Scope { get; set; }
+
+ /// <summary>
+ /// Checks the message state for conformity to the protocol specification
+ /// and throws an exception if the message is invalid.
+ /// </summary>
+ /// <remarks>
+ /// <para>Some messages have required fields, or combinations of fields that must relate to each other
+ /// in specialized ways. After deserializing a message, this method checks the state of the
+ /// message to see if it conforms to the protocol.</para>
+ /// <para>Note that this property should <i>not</i> check signatures or perform any state checks
+ /// outside this scope of this particular message.</para>
+ /// </remarks>
+ /// <exception cref="ProtocolException">Thrown if the message is invalid.</exception>
+ protected override void EnsureValidMessage() {
+ base.EnsureValidMessage();
+ ErrorUtilities.VerifyProtocol(this.Recipient.IsTransportSecure(), OAuthWrapStrings.HttpsRequired);
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/ClientAccountAndPassword/ClientAccountUsernamePasswordSuccessResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/ClientAccountAndPassword/ClientAccountUsernamePasswordSuccessResponse.cs
new file mode 100644
index 0000000..186827c
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/ClientAccountAndPassword/ClientAccountUsernamePasswordSuccessResponse.cs
@@ -0,0 +1,47 @@
+//-----------------------------------------------------------------------
+// <copyright file="ClientAccountUsernamePasswordSuccessResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A response from the Authorization Server to the Client containing an access code.
+ /// </summary>
+ internal class ClientAccountUsernamePasswordSuccessResponse : MessageBase {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ClientAccountUsernamePasswordSuccessResponse"/> class.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ internal ClientAccountUsernamePasswordSuccessResponse(ClientAccountUsernamePasswordRequest request)
+ : base(request) {
+ }
+
+ /// <summary>
+ /// Gets or sets the refresh token.
+ /// </summary>
+ /// <value>The token.</value>
+ [MessagePart(Protocol.wrap_refresh_token, IsRequired = true, AllowEmpty = false)]
+ internal string RefreshToken { get; set; }
+
+ /// <summary>
+ /// Gets or sets the access token.
+ /// </summary>
+ /// <value>The access token.</value>
+ [MessagePart(Protocol.wrap_access_token, IsRequired = true, AllowEmpty = false)]
+ internal string AccessToken { get; set; }
+
+ /// <summary>
+ /// Gets or sets the lifetime of the access token.
+ /// </summary>
+ /// <value>The lifetime.</value>
+ [MessagePart(Protocol.wrap_access_token_expires_in, IsRequired = false, Encoder = typeof(TimespanSecondsEncoder))]
+ internal TimeSpan Lifetime { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/IMessageWithClientState.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/IMessageWithClientState.cs
new file mode 100644
index 0000000..8054d27
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/IMessageWithClientState.cs
@@ -0,0 +1,13 @@
+//-----------------------------------------------------------------------
+// <copyright file="IMessageWithClientState.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using DotNetOpenAuth.Messaging;
+
+ internal interface IMessageWithClientState : IProtocolMessage {
+ string ClientState { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/MessageBase.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/MessageBase.cs
new file mode 100644
index 0000000..9986d19
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/MessageBase.cs
@@ -0,0 +1,205 @@
+//-----------------------------------------------------------------------
+// <copyright file="MessageBase.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A common message base class for OAuth WRAP messages.
+ /// </summary>
+ public class MessageBase : IDirectedProtocolMessage, IDirectResponseProtocolMessage {
+ /// <summary>
+ /// A dictionary to contain extra message data.
+ /// </summary>
+ private Dictionary<string, string> extraData = new Dictionary<string, string>();
+
+ /// <summary>
+ /// The originating request.
+ /// </summary>
+ private IDirectedProtocolMessage originatingRequest;
+
+ /// <summary>
+ /// The backing field for the <see cref="IMessage.Version"/> property.
+ /// </summary>
+ private Version version;
+
+ /// <summary>
+ /// A value indicating whether this message is a direct or indirect message.
+ /// </summary>
+ private MessageTransport messageTransport;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MessageBase"/> class
+ /// that is used for direct response messages.
+ /// </summary>
+ /// <param name="version">The version.</param>
+ protected MessageBase(Version version) {
+ Contract.Requires<ArgumentNullException>(version != null);
+ this.messageTransport = MessageTransport.Direct;
+ this.version = version;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MessageBase"/> class.
+ /// </summary>
+ /// <param name="request">The originating request.</param>
+ protected MessageBase(IDirectedProtocolMessage request) {
+ Contract.Requires<ArgumentNullException>(request != null);
+ this.originatingRequest = request;
+ this.messageTransport = MessageTransport.Direct;
+ this.version = request.Version;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MessageBase"/> class
+ /// that is used for directed messages.
+ /// </summary>
+ /// <param name="version">The version.</param>
+ /// <param name="messageTransport">The message transport.</param>
+ /// <param name="recipient">The recipient.</param>
+ protected MessageBase(Version version, MessageTransport messageTransport, Uri recipient) {
+ Contract.Requires<ArgumentNullException>(version != null);
+ Contract.Requires<ArgumentNullException>(recipient != null);
+
+ this.version = version;
+ this.messageTransport = messageTransport;
+ this.Recipient = recipient;
+ this.HttpMethods = HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.PostRequest;
+ }
+
+ #region IMessage Properties
+
+ /// <summary>
+ /// Gets the version of the protocol or extension this message is prepared to implement.
+ /// </summary>
+ /// <remarks>
+ /// Implementations of this interface should ensure that this property never returns null.
+ /// </remarks>
+ Version IMessage.Version {
+ get { return this.version; }
+ }
+
+ /// <summary>
+ /// Gets the extra, non-standard Protocol parameters included in the message.
+ /// </summary>
+ /// <value></value>
+ /// <remarks>
+ /// Implementations of this interface should ensure that this property never returns null.
+ /// </remarks>
+ public IDictionary<string, string> ExtraData {
+ get { return this.extraData; }
+ }
+
+ #endregion
+
+ #region IProtocolMessage Members
+
+ /// <summary>
+ /// Gets the level of protection this message requires.
+ /// </summary>
+ /// <value><see cref="MessageProtections.None"/></value>
+ MessageProtections IProtocolMessage.RequiredProtection {
+ get { return MessageProtections.None; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this is a direct or indirect message.
+ /// </summary>
+ /// <value></value>
+ MessageTransport IProtocolMessage.Transport {
+ get { return this.messageTransport; }
+ }
+
+ #endregion
+
+ #region IDirectedProtocolMessage Members
+
+ /// <summary>
+ /// Gets the preferred method of transport for the message.
+ /// </summary>
+ /// <remarks>
+ /// For indirect messages this will likely be GET+POST, which both can be simulated in the user agent:
+ /// the GET with a simple 301 Redirect, and the POST with an HTML form in the response with javascript
+ /// to automate submission.
+ /// </remarks>
+ HttpDeliveryMethods IDirectedProtocolMessage.HttpMethods {
+ get { return this.HttpMethods; }
+ }
+
+ /// <summary>
+ /// Gets the URL of the intended receiver of this message.
+ /// </summary>
+ Uri IDirectedProtocolMessage.Recipient {
+ get { return this.Recipient; }
+ }
+
+ #endregion
+
+ #region IDirectResponseProtocolMessage Members
+
+ /// <summary>
+ /// Gets the originating request message that caused this response to be formed.
+ /// </summary>
+ IDirectedProtocolMessage IDirectResponseProtocolMessage.OriginatingRequest {
+ get { return this.originatingRequest; }
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Gets or sets the preferred method of transport for the message.
+ /// </summary>
+ /// <remarks>
+ /// For indirect messages this will likely be GET+POST, which both can be simulated in the user agent:
+ /// the GET with a simple 301 Redirect, and the POST with an HTML form in the response with javascript
+ /// to automate submission.
+ /// </remarks>
+ protected HttpDeliveryMethods HttpMethods { get; set; }
+
+ /// <summary>
+ /// Gets the URL of the intended receiver of this message.
+ /// </summary>
+ protected Uri Recipient { get; private set; }
+
+ #region IMessage Methods
+
+ /// <summary>
+ /// Checks the message state for conformity to the protocol specification
+ /// and throws an exception if the message is invalid.
+ /// </summary>
+ /// <remarks>
+ /// <para>Some messages have required fields, or combinations of fields that must relate to each other
+ /// in specialized ways. After deserializing a message, this method checks the state of the
+ /// message to see if it conforms to the protocol.</para>
+ /// <para>Note that this property should <i>not</i> check signatures or perform any state checks
+ /// outside this scope of this particular message.</para>
+ /// </remarks>
+ /// <exception cref="ProtocolException">Thrown if the message is invalid.</exception>
+ void IMessage.EnsureValidMessage() {
+ this.EnsureValidMessage();
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Checks the message state for conformity to the protocol specification
+ /// and throws an exception if the message is invalid.
+ /// </summary>
+ /// <remarks>
+ /// <para>Some messages have required fields, or combinations of fields that must relate to each other
+ /// in specialized ways. After deserializing a message, this method checks the state of the
+ /// message to see if it conforms to the protocol.</para>
+ /// <para>Note that this property should <i>not</i> check signatures or perform any state checks
+ /// outside this scope of this particular message.</para>
+ /// </remarks>
+ /// <exception cref="ProtocolException">Thrown if the message is invalid.</exception>
+ protected virtual void EnsureValidMessage() {
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/RefreshAccessTokenFailedResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/RefreshAccessTokenFailedResponse.cs
new file mode 100644
index 0000000..43629c5
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/RefreshAccessTokenFailedResponse.cs
@@ -0,0 +1,25 @@
+//-----------------------------------------------------------------------
+// <copyright file="UserNamePasswordRefreshAccessTokenFailedResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ /// <summary>
+ /// A response from the Authorization Server to the Client to indicate that a
+ /// request for an access token renewal failed, probably due to an invalid
+ /// refresh token.
+ /// </summary>
+ /// <remarks>
+ /// This message type is shared by the Web App, Rich App, and Username/Password profiles.
+ /// </remarks>
+ internal class RefreshAccessTokenFailedResponse : UnauthorizedResponse {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RefreshAccessTokenFailedResponse"/> class.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ internal RefreshAccessTokenFailedResponse(RefreshAccessTokenRequest request)
+ : base(request) {
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/RefreshAccessTokenRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/RefreshAccessTokenRequest.cs
new file mode 100644
index 0000000..d72a958
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/RefreshAccessTokenRequest.cs
@@ -0,0 +1,57 @@
+//-----------------------------------------------------------------------
+// <copyright file="UserNamePasswordRefreshAccessTokenRequest.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A request from the client to the authorization server for a new access token
+ /// using a refresh token, after a previously supplied access token has expired.
+ /// </summary>
+ /// <remarks>
+ /// This message type is shared by the Web App, Rich App, and Username/Password profiles.
+ /// </remarks>
+ internal class RefreshAccessTokenRequest : MessageBase {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RefreshAccessTokenRequest"/> class.
+ /// </summary>
+ /// <param name="refreshTokenEndpoint">The authorization server's Refresh Token endpoint.</param>
+ /// <param name="version">The version.</param>
+ internal RefreshAccessTokenRequest(Uri refreshTokenEndpoint, Version version)
+ : base(version, MessageTransport.Direct, refreshTokenEndpoint) {
+ this.HttpMethods = HttpDeliveryMethods.PostRequest;
+ }
+
+ /// <summary>
+ /// Gets or sets the refresh token that was received in
+ /// <see cref="UserNamePasswordSuccessResponse.RefreshToken"/>.
+ /// </summary>
+ /// <value>The refresh token.</value>
+ [MessagePart(Protocol.wrap_refresh_token, IsRequired = true, AllowEmpty = false)]
+ internal string RefreshToken { get; set; }
+
+ /// <summary>
+ /// Checks the message state for conformity to the protocol specification
+ /// and throws an exception if the message is invalid.
+ /// </summary>
+ /// <remarks>
+ /// <para>Some messages have required fields, or combinations of fields that must relate to each other
+ /// in specialized ways. After deserializing a message, this method checks the state of the
+ /// message to see if it conforms to the protocol.</para>
+ /// <para>Note that this property should <i>not</i> check signatures or perform any state checks
+ /// outside this scope of this particular message.</para>
+ /// </remarks>
+ /// <exception cref="ProtocolException">Thrown if the message is invalid.</exception>
+ protected override void EnsureValidMessage() {
+ base.EnsureValidMessage();
+ ErrorUtilities.VerifyProtocol(this.Recipient.IsTransportSecure(), OAuthWrapStrings.HttpsRequired);
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/RefreshAccessTokenSuccessResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/RefreshAccessTokenSuccessResponse.cs
new file mode 100644
index 0000000..8a2b14a
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/RefreshAccessTokenSuccessResponse.cs
@@ -0,0 +1,44 @@
+//-----------------------------------------------------------------------
+// <copyright file="UserNamePasswordRefreshAccessTokenSuccessResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A response from the Authorization Server to the Consumer containing a delegation code
+ /// that the Consumer should use to obtain an access token.
+ /// </summary>
+ /// <remarks>
+ /// This message type is shared by the Web App, Rich App, and Username/Password profiles.
+ /// </remarks>
+ internal class RefreshAccessTokenSuccessResponse : MessageBase {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RefreshAccessTokenSuccessResponse"/> class.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ internal RefreshAccessTokenSuccessResponse(RefreshAccessTokenRequest request)
+ : base(request) {
+ }
+
+ /// <summary>
+ /// Gets or sets the access token.
+ /// </summary>
+ /// <value>The access token.</value>
+ [MessagePart(Protocol.wrap_access_token, IsRequired = true, AllowEmpty = false)]
+ internal string AccessToken { get; set; }
+
+ /// <summary>
+ /// Gets or sets the lifetime of the access token.
+ /// </summary>
+ /// <value>The lifetime.</value>
+ [MessagePart(Protocol.wrap_access_token_expires_in, IsRequired = false, Encoder = typeof(TimespanSecondsEncoder))]
+ internal TimeSpan Lifetime { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppAccessTokenFailedResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppAccessTokenFailedResponse.cs
new file mode 100644
index 0000000..be4f001
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppAccessTokenFailedResponse.cs
@@ -0,0 +1,21 @@
+//-----------------------------------------------------------------------
+// <copyright file="RichAppAccessTokenFailedResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ /// <summary>
+ /// A response from the Authorization Server to the Client in the event
+ /// that an access token could not be granted.
+ /// </summary>
+ internal class RichAppAccessTokenFailedResponse : UnauthorizedResponse {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RichAppAccessTokenFailedResponse"/> class.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ internal RichAppAccessTokenFailedResponse(RichAppAccessTokenRequest request)
+ : base(request) {
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppAccessTokenRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppAccessTokenRequest.cs
new file mode 100644
index 0000000..f0ad943
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppAccessTokenRequest.cs
@@ -0,0 +1,61 @@
+//-----------------------------------------------------------------------
+// <copyright file="RichAppAccessTokenRequest.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A message from the Client to the Authorization Server exchanging a
+ /// verification code for refresh and access tokens.
+ /// </summary>
+ internal class RichAppAccessTokenRequest : MessageBase {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RichAppAccessTokenRequest"/> class.
+ /// </summary>
+ /// <param name="authorizationServer">The authorization server.</param>
+ /// <param name="version">The version.</param>
+ internal RichAppAccessTokenRequest(Uri authorizationServer, Version version)
+ : base(version, MessageTransport.Direct, authorizationServer) {
+ this.HttpMethods = HttpDeliveryMethods.PostRequest;
+ }
+
+ /// <summary>
+ /// Gets or sets the identifier by which this client is known to the Authorization Server.
+ /// </summary>
+ /// <value>The client identifier.</value>
+ [MessagePart(Protocol.wrap_client_id, IsRequired = true, AllowEmpty = false)]
+ internal string ClientIdentifier { get; set; }
+
+ /// <summary>
+ /// Gets or sets the verification code previously communicated to the Client
+ /// in <see cref="RichAppResponse.VerificationCode"/>.
+ /// </summary>
+ /// <value>The verification code.</value>
+ [MessagePart(Protocol.wrap_verification_code, IsRequired = true, AllowEmpty = false)]
+ internal string VerificationCode { get; set; }
+
+ /// <summary>
+ /// Checks the message state for conformity to the protocol specification
+ /// and throws an exception if the message is invalid.
+ /// </summary>
+ /// <remarks>
+ /// <para>Some messages have required fields, or combinations of fields that must relate to each other
+ /// in specialized ways. After deserializing a message, this method checks the state of the
+ /// message to see if it conforms to the protocol.</para>
+ /// <para>Note that this property should <i>not</i> check signatures or perform any state checks
+ /// outside this scope of this particular message.</para>
+ /// </remarks>
+ /// <exception cref="ProtocolException">Thrown if the message is invalid.</exception>
+ protected override void EnsureValidMessage() {
+ base.EnsureValidMessage();
+ ErrorUtilities.VerifyProtocol(this.Recipient.IsTransportSecure(), OAuthWrapStrings.HttpsRequired);
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppAccessTokenSuccessResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppAccessTokenSuccessResponse.cs
new file mode 100644
index 0000000..8330176
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppAccessTokenSuccessResponse.cs
@@ -0,0 +1,45 @@
+//-----------------------------------------------------------------------
+// <copyright file="RichAppAccessTokenSuccessResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// The direct response message that contains the access token from the Authorization Server
+ /// to the Client.
+ /// </summary>
+ internal class RichAppAccessTokenSuccessResponse : MessageBase {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RichAppAccessTokenSuccessResponse"/> class.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ internal RichAppAccessTokenSuccessResponse(RichAppAccessTokenRequest request)
+ : base(request) {
+ }
+
+ /// <summary>
+ /// Gets or sets the refresh token.
+ /// </summary>
+ /// <value>The token.</value>
+ [MessagePart(Protocol.wrap_refresh_token, IsRequired = true, AllowEmpty = false)]
+ internal string RefreshToken { get; set; }
+
+ /// <summary>
+ /// Gets or sets the access token.
+ /// </summary>
+ /// <value>The token.</value>
+ [MessagePart(Protocol.wrap_access_token, IsRequired = true, AllowEmpty = false)]
+ internal string AccessToken { get; set; }
+
+ /// <summary>
+ /// Gets or sets the lifetime of the access token.
+ /// </summary>
+ /// <value>The lifetime.</value>
+ [MessagePart(Protocol.wrap_access_token_expires_in, IsRequired = false, AllowEmpty = false, Encoder = typeof(TimespanSecondsEncoder))]
+ internal TimeSpan? Lifetime { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppRequest.cs
new file mode 100644
index 0000000..9856687
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppRequest.cs
@@ -0,0 +1,68 @@
+//-----------------------------------------------------------------------
+// <copyright file="RichAppRequest.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A request from a rich app Client to an Authorization Server requested
+ /// authorization to access user Protected Data.
+ /// </summary>
+ internal class RichAppRequest : MessageBase {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RichAppRequest"/> class.
+ /// </summary>
+ /// <param name="authorizationServer">The authorization server.</param>
+ /// <param name="version">The version.</param>
+ internal RichAppRequest(Uri authorizationServer, Version version)
+ : base(version, MessageTransport.Indirect, authorizationServer) {
+ }
+
+ /// <summary>
+ /// Gets or sets the client identifier previously obtained from the Authorization Server.
+ /// </summary>
+ /// <value>The client identifier.</value>
+ [MessagePart(Protocol.wrap_client_id, IsRequired = true, AllowEmpty = false)]
+ internal string ClientIdentifier { get; set; }
+
+ /// <summary>
+ /// Gets or sets the callback URL.
+ /// </summary>
+ /// <value>
+ /// An absolute URL to which the Authorization Server will redirect the User back after
+ /// the user has approved the authorization request.
+ /// </value>
+ /// <remarks>
+ /// Authorization Servers MAY require that the wrap_callback URL match the previously
+ /// registered value for the Client Identifier.
+ /// </remarks>
+ [MessagePart(Protocol.wrap_callback, IsRequired = false, AllowEmpty = false)]
+ internal Uri Callback { get; set; }
+
+ /// <summary>
+ /// Gets or sets state of the client that should be sent back with the authorization response.
+ /// </summary>
+ /// <value>
+ /// An opaque value that Clients can use to maintain state associated with this request.
+ /// </value>
+ /// <remarks>
+ /// If this value is present, the Authorization Server MUST return it to the Client's Callback URL.
+ /// </remarks>
+ [MessagePart(Protocol.wrap_client_state, IsRequired = false, AllowEmpty = true)]
+ internal string ClientState { get; set; }
+
+ /// <summary>
+ /// Gets or sets the scope.
+ /// </summary>
+ /// <value>The Authorization Server MAY define authorization scope values for the Client to include.</value>
+ [MessagePart(Protocol.wrap_scope, IsRequired = false, AllowEmpty = true)]
+ internal string Scope { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppResponse.cs
new file mode 100644
index 0000000..678d956
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/RichApp/RichAppResponse.cs
@@ -0,0 +1,60 @@
+//-----------------------------------------------------------------------
+// <copyright file="RichAppResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// An indirect response from the Authorization Server to the rich app Client
+ /// with the verification code.
+ /// </summary>
+ internal class RichAppResponse : MessageBase {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RichAppResponse"/> class.
+ /// </summary>
+ /// <param name="clientCallback">The client callback.</param>
+ /// <param name="version">The version.</param>
+ internal RichAppResponse(Uri clientCallback, Version version)
+ : base(version, MessageTransport.Indirect, clientCallback) {
+ }
+
+ /// <summary>
+ /// Gets or sets the verification code.
+ /// </summary>
+ /// <value>
+ /// The long-lived credential assigned by the Authorization Server to this Client for
+ /// use in accessing the authorizing user's protected resources.
+ /// </value>
+ [MessagePart(Protocol.wrap_verification_code, IsRequired = true, AllowEmpty = false)]
+ internal string VerificationCode { get; set; }
+
+ /// <summary>
+ /// Gets or sets state of the client that should be sent back with the authorization response.
+ /// </summary>
+ /// <value>
+ /// An opaque value that Clients can use to maintain state associated with this request.
+ /// </value>
+ /// <remarks>
+ /// This parameter is required if the Client included it in <see cref="RichAppRequest.ClientState"/>.
+ /// </remarks>
+ [MessagePart(Protocol.wrap_client_state, IsRequired = false, AllowEmpty = true)]
+ internal string ClientState { get; set; }
+
+ /// <summary>
+ /// Gets a value indicating whether the user granted the authorization request.
+ /// </summary>
+ /// <value>
+ /// <c>true</c> if authorization is granted; otherwise, <c>false</c>.
+ /// </value>
+ internal bool IsGranted {
+ get { return !string.IsNullOrEmpty(this.VerificationCode) && this.VerificationCode != Protocol.user_denied; }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/UnauthorizedResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/UnauthorizedResponse.cs
new file mode 100644
index 0000000..901b6ff
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/UnauthorizedResponse.cs
@@ -0,0 +1,47 @@
+//-----------------------------------------------------------------------
+// <copyright file="UnauthorizedResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System.Net;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A direct response that is simply a 401 Unauthorized with an
+ /// WWW-Authenticate: OAuth header.
+ /// </summary>
+ internal class UnauthorizedResponse : MessageBase, IHttpDirectResponse {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UnauthorizedResponse"/> class.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ internal UnauthorizedResponse(IDirectedProtocolMessage request)
+ : base(request) {
+ }
+
+ #region IHttpDirectResponse Members
+
+ /// <summary>
+ /// Gets the HTTP status code that the direct response should be sent with.
+ /// </summary>
+ HttpStatusCode IHttpDirectResponse.HttpStatusCode {
+ get { return HttpStatusCode.Unauthorized; }
+ }
+
+ /// <summary>
+ /// Gets the HTTP headers to add to the response.
+ /// </summary>
+ /// <value>May be an empty collection, but must not be <c>null</c>.</value>
+ WebHeaderCollection IHttpDirectResponse.Headers {
+ get {
+ return new WebHeaderCollection() {
+ { HttpResponseHeader.WwwAuthenticate, Protocol.HttpAuthorizationScheme },
+ };
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordCaptchaResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordCaptchaResponse.cs
new file mode 100644
index 0000000..192af58
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordCaptchaResponse.cs
@@ -0,0 +1,54 @@
+//-----------------------------------------------------------------------
+// <copyright file="UsernamePasswordCaptchaResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Net;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A response from the Authorization Server indicating the Client must have the user
+ /// complete a CAPTCHA puzzle prior to authorization.
+ /// </summary>
+ internal class UsernamePasswordCaptchaResponse : MessageBase, IHttpDirectResponse {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UsernamePasswordCaptchaResponse"/> class.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ internal UsernamePasswordCaptchaResponse(UserNamePasswordRequest request)
+ : base(request) {
+ }
+
+ #region IHttpDirectResponse Members
+
+ /// <summary>
+ /// Gets the HTTP status code that the direct response should be sent with.
+ /// </summary>
+ HttpStatusCode IHttpDirectResponse.HttpStatusCode {
+ get { return HttpStatusCode.BadRequest; }
+ }
+
+ /// <summary>
+ /// Gets the HTTP headers to add to the response.
+ /// </summary>
+ /// <value>May be an empty collection, but must not be <c>null</c>.</value>
+ WebHeaderCollection IHttpDirectResponse.Headers {
+ get { return new WebHeaderCollection(); }
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Gets or sets the URL to the CAPTCHA puzzle.
+ /// </summary>
+ /// <value>The captcha URL.</value>
+ [MessagePart(Protocol.wrap_captcha_url, IsRequired = true, AllowEmpty = false)]
+ internal Uri CaptchaPuzzle { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordFailedResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordFailedResponse.cs
new file mode 100644
index 0000000..fa98b83
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordFailedResponse.cs
@@ -0,0 +1,22 @@
+//-----------------------------------------------------------------------
+// <copyright file="UserNamePasswordFailedResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ /// <summary>
+ /// A response from the Authorization Server to the Consumer to indicate that a
+ /// request for a delegation code failed, probably due to an invalid
+ /// username and password.
+ /// </summary>
+ internal class UserNamePasswordFailedResponse : UnauthorizedResponse {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UserNamePasswordFailedResponse"/> class.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ internal UserNamePasswordFailedResponse(UserNamePasswordRequest request)
+ : base(request) {
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordRequest.cs
new file mode 100644
index 0000000..b4a72ff
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordRequest.cs
@@ -0,0 +1,93 @@
+//-----------------------------------------------------------------------
+// <copyright file="UserNamePasswordRequest.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A request for a delegation code in exchnage for a user's confidential
+ /// username and password.
+ /// </summary>
+ /// <remarks>
+ /// After this request has been sent, the consumer application MUST discard
+ /// the confidential user credentials and use the delegation code going forward.
+ /// </remarks>
+ internal class UserNamePasswordRequest : MessageBase {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UserNamePasswordRequest"/> class.
+ /// </summary>
+ /// <param name="authorizationServer">The authorization server.</param>
+ /// <param name="version">The version.</param>
+ internal UserNamePasswordRequest(Uri authorizationServer, Version version)
+ : base(version, MessageTransport.Direct, authorizationServer) {
+ this.HttpMethods = HttpDeliveryMethods.PostRequest;
+ }
+
+ /// <summary>
+ /// Gets or sets the client identifier previously obtained from the Authorization Server.
+ /// </summary>
+ /// <value>The client identifier.</value>
+ [MessagePart(Protocol.wrap_client_id, IsRequired = true, AllowEmpty = false)]
+ internal string ClientIdentifier { get; set; }
+
+ /// <summary>
+ /// Gets or sets the user's account username.
+ /// </summary>
+ /// <value>The username on the user's account.</value>
+ [MessagePart(Protocol.wrap_username, IsRequired = true, AllowEmpty = false)]
+ internal string UserName { get; set; }
+
+ /// <summary>
+ /// Gets or sets the user's password.
+ /// </summary>
+ /// <value>The password.</value>
+ [MessagePart(Protocol.wrap_password, IsRequired = true, AllowEmpty = false)]
+ internal string Password { get; set; }
+
+ /// <summary>
+ /// Gets or sets the CAPTCHA puzzle that the user just solved, if applicable.
+ /// </summary>
+ /// <value>The captcha puzzle location.</value>
+ [MessagePart(Protocol.wrap_captcha_url, IsRequired = false, AllowEmpty = false)]
+ internal Uri CaptchaPuzzle { get; set; }
+
+ /// <summary>
+ /// Gets or sets the solution to the CAPTCHA puzzle the user just solved, if applicable.
+ /// </summary>
+ /// <value>The CAPTCHA solution.</value>
+ [MessagePart(Protocol.wrap_captcha_solution, IsRequired = false, AllowEmpty = false)]
+ internal string CaptchaSolution { get; set; }
+
+ /// <summary>
+ /// Gets or sets the scope.
+ /// </summary>
+ /// <value>The scope.</value>
+ [MessagePart(Protocol.wrap_scope, IsRequired = false, AllowEmpty = true)]
+ internal string Scope { get; set; }
+
+ /// <summary>
+ /// Checks the message state for conformity to the protocol specification
+ /// and throws an exception if the message is invalid.
+ /// </summary>
+ /// <remarks>
+ /// <para>Some messages have required fields, or combinations of fields that must relate to each other
+ /// in specialized ways. After deserializing a message, this method checks the state of the
+ /// message to see if it conforms to the protocol.</para>
+ /// <para>Note that this property should <i>not</i> check signatures or perform any state checks
+ /// outside this scope of this particular message.</para>
+ /// </remarks>
+ /// <exception cref="ProtocolException">Thrown if the message is invalid.</exception>
+ protected override void EnsureValidMessage() {
+ base.EnsureValidMessage();
+ ErrorUtilities.VerifyProtocol(this.Recipient.IsTransportSecure(), OAuthWrapStrings.HttpsRequired);
+ ErrorUtilities.VerifyProtocol((this.CaptchaPuzzle == null) == (this.CaptchaSolution == null), "CAPTCHA puzzle and solution must either be both absent or both present.");
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordSuccessResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordSuccessResponse.cs
new file mode 100644
index 0000000..addae9f
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordSuccessResponse.cs
@@ -0,0 +1,51 @@
+//-----------------------------------------------------------------------
+// <copyright file="UserNamePasswordSuccessResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A response from the Authorization Server to the Client containing a refresh token
+ /// and an access token.
+ /// </summary>
+ internal class UserNamePasswordSuccessResponse : MessageBase {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UserNamePasswordSuccessResponse"/> class.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ internal UserNamePasswordSuccessResponse(UserNamePasswordRequest request)
+ : base(request) {
+ }
+
+ /// <summary>
+ /// Gets or sets the verification code.
+ /// </summary>
+ /// <value>
+ /// The long-lived credential assigned by the Authorization Server to this Client for
+ /// use in accessing the authorizing user's protected resources.
+ /// </value>
+ [MessagePart(Protocol.wrap_refresh_token, IsRequired = true, AllowEmpty = false)]
+ internal string RefreshToken { get; set; }
+
+ /// <summary>
+ /// Gets or sets the access token.
+ /// </summary>
+ /// <value>The access token.</value>
+ [MessagePart(Protocol.wrap_access_token, IsRequired = true, AllowEmpty = false)]
+ internal string AccessToken { get; set; }
+
+ /// <summary>
+ /// Gets or sets the lifetime of the access token.
+ /// </summary>
+ /// <value>The lifetime.</value>
+ [MessagePart(Protocol.wrap_access_token_expires_in, IsRequired = false, Encoder = typeof(TimespanSecondsEncoder))]
+ internal TimeSpan Lifetime { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordVerificationResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordVerificationResponse.cs
new file mode 100644
index 0000000..9b4602c
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/UsernameAndPassword/UserNamePasswordVerificationResponse.cs
@@ -0,0 +1,55 @@
+//-----------------------------------------------------------------------
+// <copyright file="UserNamePasswordVerificationResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Net;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A response from the Authorization Server to the client indicating that the user
+ /// must visit a URL to complete an additional verification step before proceeding.
+ /// </summary>
+ internal class UserNamePasswordVerificationResponse : MessageBase, IHttpDirectResponse {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UserNamePasswordVerificationResponse"/> class.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ internal UserNamePasswordVerificationResponse(UserNamePasswordRequest request)
+ : base(request) {
+ }
+
+ #region IHttpDirectResponse Members
+
+ /// <summary>
+ /// Gets the HTTP status code that the direct response should be sent with.
+ /// </summary>
+ /// <value><see cref="HttpStatusCode.BadRequest"/></value>
+ HttpStatusCode IHttpDirectResponse.HttpStatusCode {
+ get { return HttpStatusCode.BadRequest; }
+ }
+
+ /// <summary>
+ /// Gets the HTTP headers to add to the response.
+ /// </summary>
+ WebHeaderCollection IHttpDirectResponse.Headers {
+ get { return new WebHeaderCollection(); }
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Gets or sets the verification URL the user must visit with a browser
+ /// to complete some step to defeat automated attacks.
+ /// </summary>
+ /// <value>The verification URL.</value>
+ [MessagePart(Protocol.wrap_verification_url, IsRequired = true, AllowEmpty = false)]
+ internal Uri VerificationUrl { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppAccessTokenBadClientResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppAccessTokenBadClientResponse.cs
new file mode 100644
index 0000000..6758e93
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppAccessTokenBadClientResponse.cs
@@ -0,0 +1,22 @@
+//-----------------------------------------------------------------------
+// <copyright file="WebAppAccessTokenBadClientResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ /// <summary>
+ /// A response from the Authorization Server to the Client in the event
+ /// that the <see cref="WebAppAccessTokenRequest"/> message had an
+ /// invalid Client Identifier and Client Secret combination.
+ /// </summary>
+ internal class WebAppAccessTokenBadClientResponse : UnauthorizedResponse {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="WebAppAccessTokenBadClientResponse"/> class.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ internal WebAppAccessTokenBadClientResponse(WebAppAccessTokenRequest request)
+ : base(request) {
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppAccessTokenFailedResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppAccessTokenFailedResponse.cs
new file mode 100644
index 0000000..7cdc2a9
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppAccessTokenFailedResponse.cs
@@ -0,0 +1,56 @@
+//-----------------------------------------------------------------------
+// <copyright file="WebAppAccessTokenFailedResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Net;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A response from the Authorization Server to the Client in the event
+ /// that the <see cref="WebAppAccessTokenRequest"/> message had an
+ /// invalid calback URL or verification code.
+ /// </summary>
+ internal class WebAppAccessTokenFailedResponse : MessageBase, IHttpDirectResponse {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="WebAppAccessTokenFailedResponse"/> class.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ internal WebAppAccessTokenFailedResponse(WebAppAccessTokenRequest request)
+ : base(request) {
+ }
+
+ #region IHttpDirectResponse Members
+
+ /// <summary>
+ /// Gets the HTTP status code that the direct response should be sent with.
+ /// </summary>
+ /// <value></value>
+ HttpStatusCode IHttpDirectResponse.HttpStatusCode {
+ get { return System.Net.HttpStatusCode.BadRequest; }
+ }
+
+ /// <summary>
+ /// Gets the HTTP headers to add to the response.
+ /// </summary>
+ /// <value>May be an empty collection, but must not be <c>null</c>.</value>
+ WebHeaderCollection IHttpDirectResponse.Headers {
+ get { return new WebHeaderCollection(); }
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Gets or sets the error reason.
+ /// </summary>
+ /// <value>"expired_verification_code" or "invalid_callback".</value>
+ [MessagePart(Protocol.wrap_error_reason, IsRequired = false, AllowEmpty = true)]
+ internal string ErrorReason { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppAccessTokenRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppAccessTokenRequest.cs
new file mode 100644
index 0000000..904207e
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppAccessTokenRequest.cs
@@ -0,0 +1,90 @@
+//-----------------------------------------------------------------------
+// <copyright file="WebAppAccessTokenRequest.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OAuthWrap.ChannelElements;
+ using System.Diagnostics.Contracts;
+
+ /// <summary>
+ /// A message sent by the Client directly to the Authorization Server to exchange
+ /// the verification code for an Access Token.
+ /// </summary>
+ /// <remarks>
+ /// Used by the Web App (and Rich App?) profiles.
+ /// </remarks>
+ internal class WebAppAccessTokenRequest : MessageBase {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="WebAppAccessTokenRequest"/> class.
+ /// </summary>
+ /// <param name="accessTokenEndpoint">The Authorization Server's access token endpoint URL.</param>
+ /// <param name="version">The version.</param>
+ internal WebAppAccessTokenRequest(Uri accessTokenEndpoint, Version version)
+ : base(version, MessageTransport.Direct, accessTokenEndpoint) {
+ this.HttpMethods = HttpDeliveryMethods.PostRequest;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="WebAppAccessTokenRequest"/> class.
+ /// </summary>
+ /// <param name="authorizationServer">The authorization server.</param>
+ internal WebAppAccessTokenRequest(AuthorizationServerDescription authorizationServer)
+ : this(authorizationServer.AccessTokenEndpoint, authorizationServer.Version) {
+ Contract.Requires<ArgumentNullException>(authorizationServer != null);
+ Contract.Requires<ArgumentException>(authorizationServer.Version != null);
+ Contract.Requires<ArgumentException>(authorizationServer.AccessTokenEndpoint != null);
+ }
+
+ /// <summary>
+ /// Gets or sets the identifier by which this client is known to the Authorization Server.
+ /// </summary>
+ /// <value>The client identifier.</value>
+ [MessagePart(Protocol.wrap_client_id, IsRequired = true, AllowEmpty = false)]
+ internal string ClientIdentifier { get; set; }
+
+ /// <summary>
+ /// Gets or sets the client secret.
+ /// </summary>
+ /// <value>The client secret.</value>
+ [MessagePart(Protocol.wrap_client_secret, IsRequired = true, AllowEmpty = false)]
+ internal string ClientSecret { get; set; }
+
+ /// <summary>
+ /// Gets or sets the verification code previously communicated to the Client
+ /// in <see cref="WebAppSuccessResponse.VerificationCode"/>.
+ /// </summary>
+ /// <value>The verification code.</value>
+ [MessagePart(Protocol.wrap_verification_code, IsRequired = true, AllowEmpty = false)]
+ internal string VerificationCode { get; set; }
+
+ /// <summary>
+ /// Gets or sets the callback URL used in <see cref="WebAppRequest.Callback"/>
+ /// </summary>
+ /// <value>
+ /// The Callback URL used to obtain the Verification Code.
+ /// </value>
+ [MessagePart(Protocol.wrap_callback, IsRequired = true, AllowEmpty = false)]
+ internal Uri Callback { get; set; }
+
+ /// <summary>
+ /// Checks the message state for conformity to the protocol specification
+ /// and throws an exception if the message is invalid.
+ /// </summary>
+ /// <remarks>
+ /// <para>Some messages have required fields, or combinations of fields that must relate to each other
+ /// in specialized ways. After deserializing a message, this method checks the state of the
+ /// message to see if it conforms to the protocol.</para>
+ /// <para>Note that this property should <i>not</i> check signatures or perform any state checks
+ /// outside this scope of this particular message.</para>
+ /// </remarks>
+ /// <exception cref="ProtocolException">Thrown if the message is invalid.</exception>
+ protected override void EnsureValidMessage() {
+ base.EnsureValidMessage();
+ ErrorUtilities.VerifyProtocol(this.Recipient.IsTransportSecure(), OAuthWrapStrings.HttpsRequired);
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppAccessTokenSuccessResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppAccessTokenSuccessResponse.cs
new file mode 100644
index 0000000..ec44712
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppAccessTokenSuccessResponse.cs
@@ -0,0 +1,45 @@
+//-----------------------------------------------------------------------
+// <copyright file="WebAppAccessTokenSuccessResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// The direct response message that contains the access token from the Authorization Server
+ /// to the Client.
+ /// </summary>
+ internal class WebAppAccessTokenSuccessResponse : MessageBase {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="WebAppAccessTokenSuccessResponse"/> class.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ internal WebAppAccessTokenSuccessResponse(WebAppAccessTokenRequest request)
+ : base(request) {
+ }
+
+ /// <summary>
+ /// Gets or sets the refresh token.
+ /// </summary>
+ /// <value>The token.</value>
+ [MessagePart(Protocol.wrap_refresh_token, IsRequired = true, AllowEmpty = false)]
+ internal string RefreshToken { get; set; }
+
+ /// <summary>
+ /// Gets or sets the access token.
+ /// </summary>
+ /// <value>The token.</value>
+ [MessagePart(Protocol.wrap_access_token, IsRequired = true, AllowEmpty = false)]
+ internal string AccessToken { get; set; }
+
+ /// <summary>
+ /// Gets or sets the lifetime of the access token.
+ /// </summary>
+ /// <value>The lifetime.</value>
+ [MessagePart(Protocol.wrap_access_token_expires_in, IsRequired = false, AllowEmpty = false, Encoder = typeof(TimespanSecondsEncoder))]
+ internal TimeSpan? Lifetime { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppFailedResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppFailedResponse.cs
new file mode 100644
index 0000000..fd7f546
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppFailedResponse.cs
@@ -0,0 +1,47 @@
+//-----------------------------------------------------------------------
+// <copyright file="WebAppFailedResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using System.Diagnostics.Contracts;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// The message the Authorization Server MAY use to send the user back to the Client
+ /// following the user's denial to grant Consumer with authorization of
+ /// access to requested resources.
+ /// </summary>
+ internal class WebAppFailedResponse : MessageBase, IMessageWithClientState {
+ /// <summary>
+ /// A constant parameter that indicates the user refused to grant the requested authorization.
+ /// </summary>
+ [MessagePart(Protocol.wrap_error_reason, IsRequired = true)]
+ private const string ErrorReason = Protocol.user_denied;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="WebAppFailedResponse"/> class.
+ /// </summary>
+ /// <param name="clientCallback">The recipient of the message.</param>
+ /// <param name="version">The version.</param>
+ internal WebAppFailedResponse(Uri clientCallback, Version version) :
+ base(version, MessageTransport.Indirect, clientCallback) {
+ Contract.Requires<ArgumentNullException>(version != null);
+ Contract.Requires<ArgumentNullException>(clientCallback != null);
+ }
+
+ /// <summary>
+ /// Gets or sets the state of the client that was supplied to the Authorization Server.
+ /// </summary>
+ /// <value>
+ /// An opaque value that Clients can use to maintain state associated with the authorization request.
+ /// </value>
+ /// <remarks>
+ /// If this value is present, the Authorization Server MUST return it to the Client's callback URL.
+ /// </remarks>
+ [MessagePart(Protocol.wrap_client_state, IsRequired = false, AllowEmpty = true)]
+ internal string ClientState { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppRequest.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppRequest.cs
new file mode 100644
index 0000000..5166342
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppRequest.cs
@@ -0,0 +1,80 @@
+//-----------------------------------------------------------------------
+// <copyright file="WebAppRequest.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OAuthWrap.ChannelElements;
+ using System.Diagnostics.Contracts;
+
+ /// <summary>
+ /// A message sent by a web application Client to the AuthorizationServer
+ /// via the user agent to obtain authorization from the user and prepare
+ /// to issue an access token to the Consumer if permission is granted.
+ /// </summary>
+ internal class WebAppRequest : MessageBase, IMessageWithClientState {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="WebAppRequest"/> class.
+ /// </summary>
+ /// <param name="userAuthorizationEndpoint">The Authorization Server's user authorization URL to direct the user to.</param>
+ /// <param name="version">The protocol version.</param>
+ internal WebAppRequest(Uri userAuthorizationEndpoint, Version version)
+ : base(version, MessageTransport.Indirect, userAuthorizationEndpoint) {
+ Contract.Requires<ArgumentNullException>(userAuthorizationEndpoint != null);
+ Contract.Requires<ArgumentNullException>(version != null);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="WebAppRequest"/> class.
+ /// </summary>
+ /// <param name="authorizationServer">The authorization server.</param>
+ internal WebAppRequest(AuthorizationServerDescription authorizationServer)
+ : this(authorizationServer.UserAuthorizationEndpoint, authorizationServer.Version) {
+ Contract.Requires<ArgumentNullException>(authorizationServer != null);
+ Contract.Requires<ArgumentException>(authorizationServer.Version != null);
+ Contract.Requires<ArgumentException>(authorizationServer.UserAuthorizationEndpoint != null);
+ }
+
+ /// <summary>
+ /// Gets or sets the identifier by which this client is known to the Authorization Server.
+ /// </summary>
+ [MessagePart(Protocol.wrap_client_id, IsRequired = true, AllowEmpty = false)]
+ internal string ClientIdentifier { get; set; }
+
+ /// <summary>
+ /// Gets or sets the callback URL.
+ /// </summary>
+ /// <value>
+ /// An absolute URL to which the Authorization Server will redirect the User back after
+ /// the user has approved the authorization request.
+ /// </value>
+ /// <remarks>
+ /// Authorization Servers MAY require that the wrap_callback URL match the previously
+ /// registered value for the Client Identifier.
+ /// </remarks>
+ [MessagePart(Protocol.wrap_callback, IsRequired = true, AllowEmpty = false)]
+ internal Uri Callback { get; set; }
+
+ /// <summary>
+ /// Gets or sets state of the client that should be sent back with the authorization response.
+ /// </summary>
+ /// <value>
+ /// An opaque value that Clients can use to maintain state associated with this request.
+ /// </value>
+ /// <remarks>
+ /// If this value is present, the Authorization Server MUST return it to the Client's Callback URL.
+ /// </remarks>
+ [MessagePart(Protocol.wrap_client_state, IsRequired = false, AllowEmpty = true)]
+ internal string ClientState { get; set; }
+
+ /// <summary>
+ /// Gets or sets the scope.
+ /// </summary>
+ /// <value>The Authorization Server MAY define authorization scope values for the Client to include.</value>
+ [MessagePart(Protocol.wrap_scope, IsRequired = false, AllowEmpty = true)]
+ internal string Scope { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppSuccessResponse.cs b/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppSuccessResponse.cs
new file mode 100644
index 0000000..ec13da4
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Messages/WebApp/WebAppSuccessResponse.cs
@@ -0,0 +1,49 @@
+//-----------------------------------------------------------------------
+// <copyright file="WebAppSuccessResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap.Messages {
+ using System;
+ using System.Diagnostics.Contracts;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// The message sent by the Authorization Server to the Client via the user agent
+ /// to indicate that user authorization was granted, and to return the user
+ /// to the Client where they started their experience.
+ /// </summary>
+ internal class WebAppSuccessResponse : MessageBase, IMessageWithClientState {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="WebAppSuccessResponse"/> class.
+ /// </summary>
+ /// <param name="clientCallback">The client callback.</param>
+ /// <param name="version">The protocol version.</param>
+ internal WebAppSuccessResponse(Uri clientCallback, Version version)
+ : base(version, MessageTransport.Indirect, clientCallback) {
+ Contract.Requires<ArgumentNullException>(version != null);
+ Contract.Requires<ArgumentNullException>(clientCallback != null);
+ }
+
+ /// <summary>
+ /// Gets or sets the verification code.
+ /// </summary>
+ /// <value>
+ /// The long-lived credential assigned by the Authorization Server to this Consumer for
+ /// use in accessing the authorizing user's protected resources.
+ /// </value>
+ [MessagePart(Protocol.wrap_verification_code, IsRequired = true, AllowEmpty = true)]
+ internal string VerificationCode { get; set; }
+
+ /// <summary>
+ /// Gets or sets some state as provided by the client in the authorization request.
+ /// </summary>
+ /// <value>An opaque value defined by the client.</value>
+ /// <remarks>
+ /// REQUIRED if the Client sent the value in the <see cref="WebAppRequest"/>.
+ /// </remarks>
+ [MessagePart(Protocol.wrap_client_state, IsRequired = false, AllowEmpty = true)]
+ internal string ClientState { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/OAuthWrapStrings.Designer.cs b/src/DotNetOpenAuth/OAuthWrap/OAuthWrapStrings.Designer.cs
new file mode 100644
index 0000000..27879c4
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/OAuthWrapStrings.Designer.cs
@@ -0,0 +1,72 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30128.0
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap {
+ using System;
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class OAuthWrapStrings {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal OAuthWrapStrings() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DotNetOpenAuth.OAuthWrap.OAuthWrapStrings", typeof(OAuthWrapStrings).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to This message can only be sent over HTTPS..
+ /// </summary>
+ internal static string HttpsRequired {
+ get {
+ return ResourceManager.GetString("HttpsRequired", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/OAuthWrapStrings.resx b/src/DotNetOpenAuth/OAuthWrap/OAuthWrapStrings.resx
new file mode 100644
index 0000000..b8a8d62
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/OAuthWrapStrings.resx
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="HttpsRequired" xml:space="preserve">
+ <value>This message can only be sent over HTTPS.</value>
+ </data>
+</root> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/OAuthWrap/Protocol.cs b/src/DotNetOpenAuth/OAuthWrap/Protocol.cs
new file mode 100644
index 0000000..b8e3962
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/Protocol.cs
@@ -0,0 +1,188 @@
+// <auto-generated/> // disable StyleCop on this file
+//-----------------------------------------------------------------------
+// <copyright file="Protocol.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap {
+ using System;
+ using System.Collections.Generic;
+
+ /// <summary>
+ /// An enumeration of the OAuth WRAP protocol versions supported by this library.
+ /// </summary>
+ public enum ProtocolVersion {
+ /// <summary>
+ /// The OAuth WRAP 1.0 specification.
+ /// </summary>
+ V10,
+ }
+
+ /// <summary>
+ /// Protocol constants for OAuth WRAP.
+ /// </summary>
+ internal class Protocol {
+ /// <summary>
+ /// The HTTP authorization scheme "WRAP";
+ /// </summary>
+ internal const string HttpAuthorizationScheme = "WRAP";
+
+ /// <summary>
+ /// The format of the HTTP Authorization header value that authorizes OAuth WRAP requests.
+ /// </summary>
+ internal const string HttpAuthorizationHeaderFormat = "WRAP access_token=\"{0}\"";
+
+ /// <summary>
+ /// The "wrap_client_state" string.
+ /// </summary>
+ internal const string wrap_client_state = "wrap_client_state";
+
+ /// <summary>
+ /// The "wrap_callback" string.
+ /// </summary>
+ internal const string wrap_callback = "wrap_callback";
+
+ /// <summary>
+ /// The "wrap_client_id" string.
+ /// </summary>
+ internal const string wrap_client_id = "wrap_client_id";
+
+ /// <summary>
+ /// The "wrap_scope" string.
+ /// </summary>
+ internal const string wrap_scope = "wrap_scope";
+
+ /// <summary>
+ /// The "wrap_client_secret" string.
+ /// </summary>
+ internal const string wrap_client_secret = "wrap_client_secret";
+
+ /// <summary>
+ /// The "wrap_verification_code" string.
+ /// </summary>
+ internal const string wrap_verification_code = "wrap_verification_code";
+
+ /// <summary>
+ /// The "wrap_verification_url" string.
+ /// </summary>
+ internal const string wrap_verification_url = "wrap_verification_url";
+
+ /// <summary>
+ /// The "wrap_error_reason" string.
+ /// </summary>
+ internal const string wrap_error_reason = "wrap_error_reason";
+
+ /// <summary>
+ /// The "wrap_access_token" string.
+ /// </summary>
+ internal const string wrap_access_token = "wrap_access_token";
+
+ /// <summary>
+ /// The "wrap_refresh_token" string.
+ /// </summary>
+ internal const string wrap_refresh_token = "wrap_refresh_token";
+
+ /// <summary>
+ /// The "wrap_access_token_expires_in" string.
+ /// </summary>
+ internal const string wrap_access_token_expires_in = "wrap_access_token_expires_in";
+
+ /// <summary>
+ /// The "expired_delegation_code" string.
+ /// </summary>
+ internal const string expired_delegation_code = "expired_delegation_code";
+
+ /// <summary>
+ /// The "wrap_username" string.
+ /// </summary>
+ internal const string wrap_username = "wrap_username";
+
+ /// <summary>
+ /// The "wrap_password" string.
+ /// </summary>
+ internal const string wrap_password = "wrap_password";
+
+ /// <summary>
+ /// The "wrap_name" string.
+ /// </summary>
+ internal const string wrap_name = "wrap_name";
+
+ /// <summary>
+ /// The "wrap_assertion_format" string.
+ /// </summary>
+ internal const string wrap_assertion_format = "wrap_assertion_format";
+
+ /// <summary>
+ /// The "wrap_assertion" string.
+ /// </summary>
+ internal const string wrap_assertion = "wrap_assertion";
+
+ /// <summary>
+ /// The "wrap_SAML" string.
+ /// </summary>
+ internal const string wrap_saml = "wrap_SAML";
+
+ /// <summary>
+ /// The "wrap_SWT" string.
+ /// </summary>
+ internal const string wrap_swt = "wrap_SWT";
+
+ /// <summary>
+ /// The "wrap_captcha_url" string.
+ /// </summary>
+ internal const string wrap_captcha_url = "wrap_captcha_url";
+
+ /// <summary>
+ /// The "wrap_captcha_solution" string.
+ /// </summary>
+ internal const string wrap_captcha_solution = "wrap_captcha_solution";
+
+ /// <summary>
+ /// The "user_denied" string.
+ /// </summary>
+ internal const string user_denied = "user_denied";
+
+ /// <summary>
+ /// Gets the <see cref="Protocol"/> instance with values initialized for V1.0 of the protocol.
+ /// </summary>
+ internal static readonly Protocol V10 = new Protocol {
+ Version = new Version(1, 0),
+ ProtocolVersion = ProtocolVersion.V10,
+ };
+
+ /// <summary>
+ /// A list of all supported OAuth versions, in order starting from newest version.
+ /// </summary>
+ internal static readonly List<Protocol> AllVersions = new List<Protocol>() { V10 };
+
+ /// <summary>
+ /// The default (or most recent) supported version of the OpenID protocol.
+ /// </summary>
+ internal static readonly Protocol Default = AllVersions[0];
+
+ /// <summary>
+ /// Gets or sets the OAuth WRAP version represented by this instance.
+ /// </summary>
+ /// <value>The version.</value>
+ internal Version Version { get; private set; }
+
+ /// <summary>
+ /// Gets or sets the OAuth WRAP version represented by this instance.
+ /// </summary>
+ /// <value>The protocol version.</value>
+ internal ProtocolVersion ProtocolVersion { get; private set; }
+
+ /// <summary>
+ /// Gets the OAuth Protocol instance to use for the given version.
+ /// </summary>
+ /// <param name="version">The OAuth version to get.</param>
+ /// <returns>A matching <see cref="Protocol"/> instance.</returns>
+ public static Protocol Lookup(ProtocolVersion version) {
+ switch (version) {
+ case ProtocolVersion.V10: return Protocol.V10;
+ default: throw new ArgumentOutOfRangeException("version");
+ }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/WebAppClient.cs b/src/DotNetOpenAuth/OAuthWrap/WebAppClient.cs
new file mode 100644
index 0000000..f107180
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/WebAppClient.cs
@@ -0,0 +1,107 @@
+//-----------------------------------------------------------------------
+// <copyright file="WebAppClient.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using System.Linq;
+ using System.Text;
+ using System.Web;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OAuthWrap.Messages;
+
+ /// <summary>
+ /// An OAuth WRAP consumer designed for web applications.
+ /// </summary>
+ public class WebAppClient : ClientBase {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="WebAppClient"/> class.
+ /// </summary>
+ /// <param name="authorizationServer">The authorization server.</param>
+ public WebAppClient(AuthorizationServerDescription authorizationServer)
+ : base(authorizationServer) {
+ }
+
+ /// <summary>
+ /// Gets or sets the identifier by which this client is known to the Authorization Server.
+ /// </summary>
+ public string ClientIdentifier { get; set; }
+
+ /// <summary>
+ /// Gets or sets the client secret shared with the Authorization Server.
+ /// </summary>
+ public string ClientSecret { get; set; }
+
+ public IClientTokenManager TokenManager { get; set; }
+
+ public WebAppRequest PrepareRequestUserAuthorization(IWrapAuthorization authorizationState) {
+ Contract.Requires<ArgumentNullException>(authorizationState != null);
+ Contract.Requires<InvalidOperationException>(authorizationState.Callback != null || (HttpContext.Current != null && HttpContext.Current.Request != null), MessagingStrings.HttpContextRequired);
+ Contract.Requires<InvalidOperationException>(!string.IsNullOrEmpty(this.ClientIdentifier));
+ Contract.Ensures(Contract.Result<WebAppRequest>() != null);
+ Contract.Ensures(Contract.Result<WebAppRequest>().Callback == authorizationState.Callback);
+ Contract.Ensures(Contract.Result<WebAppRequest>().ClientIdentifier == this.ClientIdentifier);
+
+ if (authorizationState.Callback == null) {
+ authorizationState.Callback = this.Channel.GetRequestFromContext().UrlBeforeRewriting;
+ }
+
+ var request = new WebAppRequest(this.AuthorizationServer) {
+ ClientIdentifier = this.ClientIdentifier,
+ Callback = authorizationState.Callback,
+ Scope = authorizationState.Scope,
+ };
+
+ return request;
+ }
+
+ public IWrapAuthorization ProcessUserAuthorization() {
+ Contract.Requires<InvalidOperationException>(HttpContext.Current != null && HttpContext.Current.Request != null, MessagingStrings.HttpContextRequired);
+ return this.ProcessUserAuthorization(this.Channel.GetRequestFromContext());
+ }
+
+ public IWrapAuthorization ProcessUserAuthorization(HttpRequestInfo request) {
+ Contract.Requires<ArgumentNullException>(request != null);
+ Contract.Requires<InvalidOperationException>(!string.IsNullOrEmpty(this.ClientIdentifier));
+ Contract.Requires<InvalidOperationException>(!string.IsNullOrEmpty(this.ClientSecret));
+ var response = this.Channel.ReadFromRequest<IMessageWithClientState>(request);
+ if (response != null) {
+ IWrapAuthorization authorizationState = this.TokenManager.GetAuthorizationState(request.UrlBeforeRewriting, response.ClientState);
+ ErrorUtilities.VerifyProtocol(authorizationState != null, "Unexpected OAuth WRAP authorization response received with callback and client state that does not match an expected value.");
+ var success = response as WebAppSuccessResponse;
+ var failure = response as WebAppFailedResponse;
+ ErrorUtilities.VerifyProtocol(success != null || failure != null, MessagingStrings.UnexpectedMessageReceivedOfMany);
+ if (success != null) {
+ var accessTokenRequest = new WebAppAccessTokenRequest(this.AuthorizationServer) {
+ ClientSecret = this.ClientSecret,
+ ClientIdentifier = this.ClientIdentifier,
+ Callback = authorizationState.Callback,
+ VerificationCode = success.VerificationCode,
+ };
+ IProtocolMessage accessTokenResponse = this.Channel.Request(accessTokenRequest);
+ var accessTokenSuccess = accessTokenResponse as WebAppAccessTokenSuccessResponse;
+ var badClientAccessTokenResponse = accessTokenResponse as WebAppAccessTokenBadClientResponse;
+ var failedAccessTokenResponse = accessTokenResponse as WebAppAccessTokenFailedResponse;
+ if (accessTokenSuccess != null) {
+ authorizationState.AccessToken = accessTokenSuccess.AccessToken;
+ authorizationState.RefreshToken = accessTokenSuccess.RefreshToken;
+ authorizationState.AccessTokenExpirationUtc = DateTime.UtcNow + accessTokenSuccess.Lifetime;
+ } else if (badClientAccessTokenResponse != null) {
+ ErrorUtilities.ThrowProtocol("Failed to obtain access token due to invalid Client Identifier or Client Secret.");
+ } else { // failedAccessTokenResponse != null
+ ErrorUtilities.ThrowProtocol("Failed to obtain access token. Authorization Server reports reason: {0}", failedAccessTokenResponse.ErrorReason);
+ }
+ } else { // failure
+ }
+
+ return authorizationState;
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuthWrap/WrapUtilities.cs b/src/DotNetOpenAuth/OAuthWrap/WrapUtilities.cs
new file mode 100644
index 0000000..a892364
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuthWrap/WrapUtilities.cs
@@ -0,0 +1,34 @@
+//-----------------------------------------------------------------------
+// <copyright file="WrapUtilities.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuthWrap {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using System.Linq;
+ using System.Net;
+ using System.Text;
+
+ /// <summary>
+ /// Some common utility methods for OAuth WRAP.
+ /// </summary>
+ public static class WrapUtilities {
+ /// <summary>
+ /// Authorizes an HTTP request using an OAuth WRAP access token in an HTTP Authorization header.
+ /// </summary>
+ /// <param name="request">The request to authorize.</param>
+ /// <param name="accessToken">The access token previously obtained from the Authorization Server.</param>
+ public static void AuthorizeWithOAuthWrap(this HttpWebRequest request, string accessToken) {
+ Contract.Requires<ArgumentNullException>(request != null);
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(accessToken));
+ request.Headers[HttpRequestHeader.Authorization] = string.Format(
+ CultureInfo.InvariantCulture,
+ Protocol.HttpAuthorizationHeaderFormat,
+ accessToken);
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/Messages/DirectErrorResponse.cs b/src/DotNetOpenAuth/OpenId/Messages/DirectErrorResponse.cs
index ad20ff7..ec2f7d5 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/DirectErrorResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/DirectErrorResponse.cs
@@ -36,6 +36,14 @@ namespace DotNetOpenAuth.OpenId.Messages {
get { return HttpStatusCode.BadRequest; }
}
+ /// <summary>
+ /// Gets the HTTP headers to add to the response.
+ /// </summary>
+ /// <value>May be an empty collection, but must not be <c>null</c>.</value>
+ WebHeaderCollection IHttpDirectResponse.Headers {
+ get { return new WebHeaderCollection(); }
+ }
+
#endregion
/// <summary>