/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.rest;

import java.security.Principal;
import java.util.logging.Level;

import org.restlet.Context;
import org.restlet.Guard;
import org.restlet.data.ChallengeScheme;
import org.restlet.data.Request;
import org.xwiki.rest.resources.BrowserAuthenticationResource;

import com.xpn.xwiki.XWiki;
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.user.api.XWikiUser;

public class XWikiAuthentication extends Guard
{
    public XWikiAuthentication(Context context) throws IllegalArgumentException
    {
        super(context, ChallengeScheme.HTTP_BASIC, "XWiki");
    }

    @Override
    public int authenticate(Request request)
    {
        /* This is a special case that is used to send back a challenge to popup the authentication dialog in browsers */
        if (request.getResourceRef().getPath().endsWith(BrowserAuthenticationResource.URI_PATTERN)) {
            return super.authenticate(request);
        }

        /*
         * Try to authenticate using information in the request (authorization header or a URI in the form of
         * http://user:password@host/..., etc.)
         */
        if (super.authenticate(request) == 1) {
            /* If it's succesfull then the context has ben set with the authenticated user */
            return 1;
        }

        /* If authentication failed then no information is present in headers or URI, try to check cookies */
        XWikiContext xwikiContext = (XWikiContext) getContext().getAttributes().get(Constants.XWIKI_CONTEXT);
        XWiki xwiki = (XWiki) getContext().getAttributes().get(Constants.XWIKI);

        try {
            XWikiUser xwikiUser = xwiki.getAuthService().checkAuth(xwikiContext);
            if (xwikiUser != null) {
                xwikiContext.setUser(xwikiUser.getUser());
                getLogger().log(Level.FINE, String.format("Authenticated as '%s'.", xwikiUser.getUser()));

                getContext().getAttributes().put(Constants.XWIKI_USER, xwikiUser.getUser());
                
                return 1;
            }
        } catch (XWikiException e) {
            getLogger().log(Level.WARNING, "Exception occurred while authenticating.", e);
        }

        /*
         * If we are here all the previous authentication methods failed, so guest will be the user set for the context
         * of this request.
         */
        String xwikiUser = "XWiki.XWikiGuest";
        xwikiContext.setUser(xwikiUser);
        getContext().getAttributes().put(Constants.XWIKI_USER, xwikiUser);
        
        return 1;
    }

    @Override
    public boolean checkSecret(Request request, String identifier, char[] secret)
    {
        XWikiContext xwikiContext = (XWikiContext) getContext().getAttributes().get(Constants.XWIKI_CONTEXT);
        XWiki xwiki = (XWiki) getContext().getAttributes().get(Constants.XWIKI);

        try {
            Principal principal = xwiki.getAuthService().authenticate(identifier, new String(secret), xwikiContext);
            if (principal != null) {
                String xwikiUser = principal.getName();

                xwikiContext.setUser(xwikiUser);
                getLogger().log(Level.FINE, String.format("Authenticated as '%s'.", identifier));

                getContext().getAttributes().put(Constants.XWIKI_USER, xwikiUser);

                return true;
            }
        } catch (XWikiException e) {
            getLogger().log(Level.WARNING, "Exception occurred while authenticating.", e);
        }

        getLogger().log(Level.WARNING, String.format("Cannot authenticate '%s'.", identifier));

        return false;
    }

}

@@ -1072,16 +1072,46 @@
 Scheme;%0A
+import org.restlet.data.Form;%0A
 import o
@@ -1199,16 +1199,63 @@
 ource;%0A%0A
+import com.noelios.restlet.http.HttpConstants;%0A
 import c
@@ -1660,130 +1660,8 @@
   %7B%0A
-        /* This is a special case that is used to send back a challenge to popup the authentication dialog in browsers */%0A
     
@@ -1829,322 +1829,361 @@
     
-/*%0A         * Try to authenticate using information in the request (authorization header or a URI in the form of%0A         * http://user:password@host/..., etc.)%0A         */%0A        if (super.authenticate(request) == 1) %7B%0A            /* If it's succesfull then the context has ben set with the authenticated user */
+XWikiContext xwikiContext = (XWikiContext) getContext().getAttributes().get(Constants.XWIKI_CONTEXT);%0A        XWiki xwiki = (XWiki) getContext().getAttributes().get(Constants.XWIKI);%0A%0A        Form headers = (Form) request.getAttributes().get(HttpConstants.ATTRIBUTE_HEADERS);%0A%0A        if (headers.getValues(HttpConstants.HEADER_AUTHORIZATION) == null) %7B
 %0A   
@@ -2187,33 +2187,26 @@
             
-return 1;
+/*
 %0A        %7D%0A%0A
@@ -2206,313 +2206,210 @@
     
-%7D%0A%0A
      
-   /
 * If 
-au
 the
-ntication failed then no information is present in headers or URI, try to check cookies */%0A        XWikiContext xwikiContext = (XWikiContext) getContext().getAttributes().get(Constants.XWIKI_CONTEXT);%0A        XWiki xwiki = (XWiki) getContext().getAttributes().get(Constants.XWIKI);%0A%0A
+re isn't an authorization header, check if the context contains an already authenticated session.%0A             * If it's the case use the previously authenticated user.%0A             */%0A    
     
@@ -2410,32 +2410,36 @@
           try %7B%0A
+    
             XWik
@@ -2512,24 +2512,28 @@
             
+    
 if (xwikiUse
@@ -2537,32 +2537,36 @@
 User != null) %7B%0A
+    
                 
@@ -2616,32 +2616,36 @@
                 
+ 
+   
 getLogger().log(
@@ -2716,24 +2716,28 @@
 tUser()));%0A%0A
+    
             
@@ -2837,49 +2837,14 @@
     
+%7D
 %0A    
-            return 1;%0A            %7D%0A
     
@@ -2880,32 +2880,36 @@
 ) %7B%0A            
+    
 getLogger().log(
@@ -2983,21 +2983,14 @@
     
-%7D%0A%0A
     
-    /*
+%7D%0A
 %0A   
@@ -2999,347 +2999,74 @@
     
-* If we are here all the previous authentication methods failed, so guest will be the user set for the context%0A         * of this request.%0A         */%0A        String xwikiUser = %22XWiki.XWikiGuest%22;%0A        xwikiContext.setUser(xwikiUser);%0A        getContext().getAttributes().put(Constants.XWIKI_USER, xwikiUser);%0A        %0A        return 1
+   return 1;%0A        %7D%0A%0A        return super.authenticate(request)
 ;%0A  

Add the support for authentication through URIs in REST API